MDL-31270 mod_assign: introducing the assignment module
authorDamyon Wiese <damyon.wiese@netspot.com.au>
Thu, 3 May 2012 06:44:06 +0000 (14:44 +0800)
committerDan Poltawski <dan@moodle.com>
Thu, 3 May 2012 06:44:06 +0000 (14:44 +0800)
* Includes an assignment upgrade tool to convert from the old mod_assignment.
* Hides mod_assignment on new installs

102 files changed:
admin/tool/assignmentupgrade/batchupgrade.php [new file with mode: 0644]
admin/tool/assignmentupgrade/index.php [new file with mode: 0644]
admin/tool/assignmentupgrade/lang/en/tool_assignmentupgrade.php [new file with mode: 0644]
admin/tool/assignmentupgrade/lib.php [new file with mode: 0644]
admin/tool/assignmentupgrade/listnotupgraded.php [new file with mode: 0644]
admin/tool/assignmentupgrade/locallib.php [new file with mode: 0644]
admin/tool/assignmentupgrade/module.js [new file with mode: 0644]
admin/tool/assignmentupgrade/renderer.php [new file with mode: 0644]
admin/tool/assignmentupgrade/settings.php [new file with mode: 0644]
admin/tool/assignmentupgrade/styles.css [new file with mode: 0644]
admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php [new file with mode: 0644]
admin/tool/assignmentupgrade/upgradableassignmentstable.php [new file with mode: 0644]
admin/tool/assignmentupgrade/upgradesingle.php [new file with mode: 0644]
admin/tool/assignmentupgrade/upgradesingleconfirm.php [new file with mode: 0644]
admin/tool/assignmentupgrade/version.php [new file with mode: 0644]
mod/assign/adminlib.php [new file with mode: 0644]
mod/assign/adminmanageplugins.php [new file with mode: 0644]
mod/assign/assignmentplugin.php [new file with mode: 0644]
mod/assign/backup/moodle2/backup_assign_activity_task.class.php [new file with mode: 0644]
mod/assign/backup/moodle2/backup_assign_stepslib.php [new file with mode: 0644]
mod/assign/backup/moodle2/restore_assign_activity_task.class.php [new file with mode: 0644]
mod/assign/backup/moodle2/restore_assign_stepslib.php [new file with mode: 0644]
mod/assign/db/access.php [new file with mode: 0644]
mod/assign/db/events.php [new file with mode: 0644]
mod/assign/db/install.xml [new file with mode: 0644]
mod/assign/db/log.php [new file with mode: 0644]
mod/assign/db/messages.php [new file with mode: 0644]
mod/assign/db/subplugins.php [new file with mode: 0644]
mod/assign/db/upgrade.php [new file with mode: 0644]
mod/assign/feedback/comments/backup/moodle2/backup_assignfeedback_comments_subplugin.class.php [new file with mode: 0644]
mod/assign/feedback/comments/backup/moodle2/restore_assignfeedback_comments_subplugin.class.php [new file with mode: 0644]
mod/assign/feedback/comments/db/access.php [new file with mode: 0644]
mod/assign/feedback/comments/db/install.php [new file with mode: 0644]
mod/assign/feedback/comments/db/install.xml [new file with mode: 0644]
mod/assign/feedback/comments/db/upgrade.php [new file with mode: 0644]
mod/assign/feedback/comments/lang/en/assignfeedback_comments.php [new file with mode: 0644]
mod/assign/feedback/comments/locallib.php [new file with mode: 0644]
mod/assign/feedback/comments/version.php [new file with mode: 0644]
mod/assign/feedback/file/backup/moodle2/backup_assignfeedback_file_subplugin.class.php [new file with mode: 0644]
mod/assign/feedback/file/backup/moodle2/restore_assignfeedback_file_subplugin.class.php [new file with mode: 0644]
mod/assign/feedback/file/db/access.php [new file with mode: 0644]
mod/assign/feedback/file/db/install.php [new file with mode: 0644]
mod/assign/feedback/file/db/install.xml [new file with mode: 0644]
mod/assign/feedback/file/db/upgrade.php [new file with mode: 0644]
mod/assign/feedback/file/lang/en/assignfeedback_file.php [new file with mode: 0644]
mod/assign/feedback/file/lib.php [new file with mode: 0644]
mod/assign/feedback/file/locallib.php [new file with mode: 0644]
mod/assign/feedback/file/version.php [new file with mode: 0644]
mod/assign/feedbackplugin.php [new file with mode: 0644]
mod/assign/gradeform.php [new file with mode: 0644]
mod/assign/gradingactionsform.php [new file with mode: 0644]
mod/assign/gradingbatchoperationsform.php [new file with mode: 0644]
mod/assign/gradingoptionsform.php [new file with mode: 0644]
mod/assign/gradingtable.php [new file with mode: 0644]
mod/assign/index.php [new file with mode: 0644]
mod/assign/lang/en/assign.php [new file with mode: 0644]
mod/assign/lib.php [new file with mode: 0644]
mod/assign/locallib.php [new file with mode: 0644]
mod/assign/mod_form.php [new file with mode: 0644]
mod/assign/module.js [new file with mode: 0644]
mod/assign/pix/gradefeedback.gif [new file with mode: 0644]
mod/assign/pix/icon.gif [new file with mode: 0644]
mod/assign/portfolio_callback.php [new file with mode: 0644]
mod/assign/renderable.php [new file with mode: 0644]
mod/assign/renderer.php [new file with mode: 0644]
mod/assign/settings.php [new file with mode: 0644]
mod/assign/styles.css [new file with mode: 0644]
mod/assign/submission/comments/db/access.php [new file with mode: 0644]
mod/assign/submission/comments/db/install.php [new file with mode: 0644]
mod/assign/submission/comments/db/upgrade.php [new file with mode: 0644]
mod/assign/submission/comments/lang/en/assignsubmission_comments.php [new file with mode: 0644]
mod/assign/submission/comments/lib.php [new file with mode: 0644]
mod/assign/submission/comments/locallib.php [new file with mode: 0644]
mod/assign/submission/comments/version.php [new file with mode: 0644]
mod/assign/submission/file/backup/moodle2/backup_assignsubmission_file_subplugin.class.php [new file with mode: 0644]
mod/assign/submission/file/backup/moodle2/restore_assignsubmission_file_subplugin.class.php [new file with mode: 0644]
mod/assign/submission/file/db/access.php [new file with mode: 0644]
mod/assign/submission/file/db/install.xml [new file with mode: 0644]
mod/assign/submission/file/db/upgrade.php [new file with mode: 0644]
mod/assign/submission/file/lang/en/assignsubmission_file.php [new file with mode: 0644]
mod/assign/submission/file/lib.php [new file with mode: 0644]
mod/assign/submission/file/locallib.php [new file with mode: 0644]
mod/assign/submission/file/settings.php [new file with mode: 0644]
mod/assign/submission/file/version.php [new file with mode: 0644]
mod/assign/submission/onlinetext/backup/moodle2/backup_assignsubmission_onlinetext_subplugin.class.php [new file with mode: 0644]
mod/assign/submission/onlinetext/backup/moodle2/restore_assignsubmission_onlinetext_subplugin.class.php [new file with mode: 0644]
mod/assign/submission/onlinetext/db/access.php [new file with mode: 0644]
mod/assign/submission/onlinetext/db/install.php [new file with mode: 0644]
mod/assign/submission/onlinetext/db/install.xml [new file with mode: 0644]
mod/assign/submission/onlinetext/db/upgrade.php [new file with mode: 0644]
mod/assign/submission/onlinetext/lang/en/assignsubmission_onlinetext.php [new file with mode: 0644]
mod/assign/submission/onlinetext/lib.php [new file with mode: 0644]
mod/assign/submission/onlinetext/locallib.php [new file with mode: 0644]
mod/assign/submission/onlinetext/version.php [new file with mode: 0644]
mod/assign/submission_form.php [new file with mode: 0644]
mod/assign/submissionplugin.php [new file with mode: 0644]
mod/assign/upgradelib.php [new file with mode: 0644]
mod/assign/version.php [new file with mode: 0644]
mod/assign/view.php [new file with mode: 0644]
mod/assignment/db/install.php [new file with mode: 0644]
mod/assignment/lang/en/assignment.php
mod/assignment/lib.php

diff --git a/admin/tool/assignmentupgrade/batchupgrade.php b/admin/tool/assignmentupgrade/batchupgrade.php
new file mode 100644 (file)
index 0000000..b62260e
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Script to show all the assignments that have not been upgraded after the main upgrade.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(dirname(__FILE__) . '/../../../config.php');
+require_once(dirname(__FILE__) . '/locallib.php');
+require_once(dirname(__FILE__) . '/upgradableassignmentstable.php');
+require_once(dirname(__FILE__) . '/upgradableassignmentsbatchform.php');
+require_once($CFG->libdir . '/adminlib.php');
+
+// admin_externalpage_setup calls require_login and checks moodle/site:config
+admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('batchupgrade'));
+$PAGE->navbar->add(get_string('batchupgrade', 'tool_assignmentupgrade'));
+
+$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
+
+$confirm = required_param('confirm', PARAM_BOOL);
+if (!$confirm) {
+    print_error('invalidrequest');
+    die();
+}
+$result = tool_assignmentupgrade_upgrade_multiple_assignments(optional_param('upgradeall', 0, PARAM_BOOL),
+                                                explode(',', optional_param('selected', '', PARAM_TEXT)));
+
+echo $renderer->convert_multiple_assignments_result($result);
diff --git a/admin/tool/assignmentupgrade/index.php b/admin/tool/assignmentupgrade/index.php
new file mode 100644 (file)
index 0000000..bb7ff49
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This tool can upgrade old assignment activities to the new assignment activity type
+ *
+ * The upgrade can be done on any old assignment instance providing it is using one of the core
+ * assignment subtypes (online text, single upload, etc).
+ * The new assignment module was introduced in Moodle 2.3 and although it completely reproduces
+ * the features of the existing assignment type it wasn't designed to replace it entirely as there
+ * are many custom assignment types people use and it wouldn't be practical to try to convert them.
+ * Instead the existing assignment type will be left in core and people will be encouraged to
+ * use the new assignment type.
+ *
+ * This screen is the main entry-point to the plugin, it gives the admin a list
+ * of options available to them.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(dirname(__FILE__) . '/../../../config.php');
+require_once(dirname(__FILE__) . '/locallib.php');
+require_once($CFG->libdir . '/adminlib.php');
+
+// admin_externalpage_setup calls require_login and checks moodle/site:config
+admin_externalpage_setup('assignmentupgrade');
+
+$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
+
+$actions = array();
+
+$header = get_string('pluginname', 'tool_assignmentupgrade');
+$actions[] = tool_assignmentupgrade_action::make('listnotupgraded');
+
+echo $renderer->index_page($header, $actions);
\ No newline at end of file
diff --git a/admin/tool/assignmentupgrade/lang/en/tool_assignmentupgrade.php b/admin/tool/assignmentupgrade/lang/en/tool_assignmentupgrade.php
new file mode 100644 (file)
index 0000000..3b3734b
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Strings for the assignment upgrade tool
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['areyousure'] = 'Are you sure?';
+$string['areyousuremessage'] = 'Are you sure you want to upgrade the assignment "{$a->name}"?';
+$string['assignmentid'] = 'Assignment ID';
+$string['assignmentnotfound'] = 'Assignment could not be found (id={$a})';
+$string['assignmenttype'] = 'Assignment type';
+$string['backtoindex'] = 'Back to index';
+$string['batchoperations'] = 'Batch operations';
+$string['batchupgrade'] = 'Upgrade multiple assignments';
+$string['confirmbatchupgrade'] = 'Confirm batch upgrade assignments';
+$string['conversioncomplete'] = 'Assignment converted';
+$string['conversionfailed'] = 'The assignment conversion was not successful. The log from the upgrade was: <br />{$a}';
+$string['listnotupgraded'] = 'List assignments that have not been upgraded';
+$string['listnotupgraded_desc'] = 'You can upgrade individual assignments from here';
+$string['noassignmentstoupgrade'] = 'There are no assignments that require upgrading';
+$string['notsupported'] = '';
+$string['notupgradedintro'] = 'This page lists the assignments created with an older version of Moodle that have not been upgraded to the new assignment module in Moodle 2.3. Not all assignments can be upgraded - if they were created with a custom assignment subtype, then that subtype will need to be upgraded to the new assignment plugin format in order to complete the upgrade.';
+$string['notupgradedtitle'] = 'Assignments not upgraded';
+$string['pluginname'] = 'Assignment upgrade helper';
+$string['select'] = 'Select';
+$string['submissions'] = 'Submissions';
+$string['supported'] = 'Upgrade';
+$string['unknown'] = 'Unknown';
+$string['upgradeassignmentsummary'] = 'Upgrade assignment: {$a->name} (Course: {$a->shortname})';
+$string['upgradeassignmentsuccess'] = 'Result: Upgrade successful';
+$string['upgradeassignmentfailed'] = 'Result: Upgrade failed. The log from the upgrade was: <br/><div class="tool_assignmentupgrade_upgradelog">{$a->log}</div>';
+$string['upgradable'] = 'Upgradable';
+$string['upgradeselected'] = 'Upgrade selected assignments';
+$string['upgradeselectedcount'] = 'Upgrade {$a} selected assignments?';
+$string['upgradeall'] = 'Upgrade all assignments';
+$string['upgradeallconfirm'] = 'Upgrade all assignments?';
+$string['upgradesingle'] = 'Upgrade single assignment';
+$string['viewcourse'] = 'View the course with the converted assignment';
diff --git a/admin/tool/assignmentupgrade/lib.php b/admin/tool/assignmentupgrade/lib.php
new file mode 100644 (file)
index 0000000..d5601fa
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Lib functions (cron) to automatically complete the assignment module upgrade if it was not done all at once during the main upgrade.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+/**
+ * Standard cron function
+ */
+function tool_assignmentupgrade_cron() {
+    $settings = get_config('tool_assignmentupgrade');
+    if (empty($settings->cronenabled)) {
+        return;
+    }
+
+    mtrace('assignmentupgrade: tool_assignmentupgrade_cron() started at '. date('H:i:s'));
+    try {
+        tool_assignmentupgrade_process($settings);
+    } catch (Exception $e) {
+        mtrace('assignmentupgrade: tool_assignmentupgrade_cron() failed with an exception:');
+        mtrace($e->getMessage());
+    }
+    mtrace('assignmentupgrade: tool_assignmentupgrade_cron() finished at ' . date('H:i:s'));
+}
+
+/**
+ * This function does the cron process within the time range according to settings.
+ * This is not implemented yet
+ * @param stdClass $settings - not used
+ */
+function tool_assignmentupgrade_process($settings) {
+    global $CFG;
+    require_once(dirname(__FILE__) . '/locallib.php');
+
+    mtrace('assignmentupgrade: processing ...');
+
+    mtrace('assignmentupgrade: Done.');
+    return;
+}
diff --git a/admin/tool/assignmentupgrade/listnotupgraded.php b/admin/tool/assignmentupgrade/listnotupgraded.php
new file mode 100644 (file)
index 0000000..488ec6e
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Script to show all the assignments that have not been upgraded after the main upgrade.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(dirname(__FILE__) . '/../../../config.php');
+require_once(dirname(__FILE__) . '/locallib.php');
+require_once(dirname(__FILE__) . '/upgradableassignmentstable.php');
+require_once(dirname(__FILE__) . '/upgradableassignmentsbatchform.php');
+require_once($CFG->libdir . '/adminlib.php');
+
+// admin_externalpage_setup calls require_login and checks moodle/site:config
+admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('listnotupgraded'));
+$PAGE->navbar->add(get_string('listnotupgraded', 'tool_assignmentupgrade'));
+
+$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
+
+$perpage = get_user_preferences('tool_assignmentupgrade_perpage', 5);
+$assignments = new tool_assignmentupgrade_assignments_table($perpage);
+
+$batchform = new tool_assignmentupgrade_batchoperations_form();
+$data = $batchform->get_data();
+if ($data && $data->selectedassignments != '' || $data && isset($data->upgradeall)) {
+    echo $renderer->confirm_batch_operation_page($data);
+} else {
+    echo $renderer->assignment_list_page($assignments, $batchform);
+}
+
+
diff --git a/admin/tool/assignmentupgrade/locallib.php b/admin/tool/assignmentupgrade/locallib.php
new file mode 100644 (file)
index 0000000..89e0e24
--- /dev/null
@@ -0,0 +1,245 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Assignment upgrade tool library functions
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Get the URL of a script within this plugin.
+ * @param string $script the script name, without .php. E.g. 'index'
+ * @param array $params URL parameters (optional)
+ * @return moodle_url
+ */
+function tool_assignmentupgrade_url($script, $params = array()) {
+    return new moodle_url('/admin/tool/assignmentupgrade/' . $script . '.php', $params);
+}
+
+/**
+ * Class to encapsulate the continue / cancel for batch operations
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_assignmentupgrade_batchoperationconfirm implements renderable {
+    /** @var string $continuemessage The message to show above the continue cancel buttons */
+    public $continuemessage = '';
+    /** @var string $continueurl The url to load if the user clicks continue */
+    public $continueurl;
+
+    /**
+     * Constructor for this class
+     * @param stdClass $data - The data from the previous batch form
+     */
+    function __construct($data) {
+        if (isset($data->upgradeselected)) {
+            $this->continuemessage = get_string('upgradeselectedcount', 'tool_assignmentupgrade', count(explode(',', $data->selectedassignments)));
+            $this->continueurl = new moodle_url('/admin/tool/assignmentupgrade/batchupgrade.php', array('upgradeselected'=>'1', 'confirm'=>'1', 'sesskey'=>sesskey(), 'selected'=>$data->selectedassignments));
+        } else if (isset($data->upgradeall)) {
+            if (!tool_assignmentupgrade_any_upgradable_assignments()) {
+                $this->continuemessage = get_string('noassignmentstoupgrade', 'tool_assignmentupgrade');
+                $this->continueurl = '';
+            } else {
+                $this->continuemessage = get_string('upgradeallconfirm', 'tool_assignmentupgrade');
+                $this->continueurl = new moodle_url('/admin/tool/assignmentupgrade/batchupgrade.php', array('upgradeall'=>'1', 'confirm'=>'1', 'sesskey'=>sesskey()));
+            }
+        }
+    }
+}
+
+
+/**
+ * Class to encapsulate one of the functionalities that this plugin offers.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_assignmentupgrade_action {
+    /** @var string the name of this action. */
+    public $name;
+    /** @var moodle_url the URL to launch this action. */
+    public $url;
+    /** @var string a description of this aciton. */
+    public $description;
+
+    /**
+     * Constructor to set the fields.
+     *
+     * In order to create a new tool_assignmentupgrade_action instance you must use the tool_assignmentupgrade_action::make
+     * method.
+     *
+     * @param string $name the name of this action.
+     * @param moodle_url $url the URL to launch this action.
+     * @param string $description a description of this aciton.
+     */
+    protected function __construct($name, moodle_url $url, $description) {
+        $this->name = $name;
+        $this->url = $url;
+        $this->description = $description;
+    }
+
+    /**
+     * Make an action with standard values.
+     * @param string $shortname internal name of the action. Used to get strings and build a URL.
+     * @param array $params any URL params required.
+     * @return tool_assignmentupgrade_action
+     */
+    public static function make($shortname, $params = array()) {
+        return new self(
+                get_string($shortname, 'tool_assignmentupgrade'),
+                tool_assignmentupgrade_url($shortname, $params),
+                get_string($shortname . '_desc', 'tool_assignmentupgrade'));
+    }
+}
+
+/**
+ * Determine if there are any assignments that can be upgraded
+ * @return boolean - Are there any assignments that can be upgraded
+ */
+function tool_assignmentupgrade_any_upgradable_assignments() {
+    global $DB, $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    // first find all the unique assignment types
+    $types = $DB->get_records_sql('SELECT plugin AS assignmenttype, value AS version FROM {config_plugins} WHERE name = ? AND plugin LIKE ?', array('version', 'assignment_%'));
+
+    $upgradabletypes = array();
+
+    foreach ($types as $assignment) {
+        $shorttype = substr($assignment->assignmenttype, strlen('assignment_'));
+        if (assign::can_upgrade_assignment($shorttype, $assignment->version)) {
+            $upgradabletypes[] = $shorttype;
+        }
+    }
+    $paramlist = '?';
+    foreach ($upgradabletypes as $index => $upgradabletype) {
+        if ($index > 0) {
+            $paramlist .= ', ?';
+        }
+    }
+
+    $record = $DB->get_record_sql('SELECT COUNT(id) as count from {assignment} where assignmenttype in (' . $paramlist . ')', $upgradabletypes);
+
+    return $record->count > 0;
+}
+
+/**
+ * Load a list of all the assignmentids that can be upgraded
+ * @return array of assignment ids
+ */
+function tool_assignmentupgrade_load_all_upgradable_assignmentids() {
+    global $DB, $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    // first find all the unique assignment types
+    $types = $DB->get_records_sql('SELECT plugin AS assignmenttype, value AS version FROM {config_plugins} WHERE name = ? AND plugin LIKE ?', array('version', 'assignment_%'));
+
+    $upgradabletypes = array();
+
+    foreach ($types as $assignment) {
+        $shorttype = substr($assignment->assignmenttype, strlen('assignment_'));
+        if (assign::can_upgrade_assignment($shorttype, $assignment->version)) {
+            $upgradabletypes[] = $shorttype;
+        }
+    }
+    $paramlist = '?';
+    foreach ($upgradabletypes as $index => $upgradabletype) {
+        if ($index > 0) {
+            $paramlist .= ', ?';
+        }
+    }
+
+    $records = $DB->get_records_sql('SELECT id from {assignment} where assignmenttype in (' . $paramlist . ')', $upgradabletypes);
+    $ids = array();
+    foreach ($records as $record) {
+        $ids[] = $record->id;
+    }
+
+    return $ids;
+}
+
+
+/**
+ * Convert a list of assignments from the old format to the new one.
+ * @param bool $upgradeall - Upgrade all possible assignments
+ * @param array $assignmentids An array of assignment ids to upgrade
+ * @return array of $entry['assignmentsummary' => (result from tool_assignmentupgrade_get_assignment)
+ *                  $entry['success'] => boolean
+ *                  $entry['log'] => string - upgrade log
+ */
+function tool_assignmentupgrade_upgrade_multiple_assignments($upgradeall, $assignmentids) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    require_once($CFG->dirroot . '/mod/assign/upgradelib.php');
+    $upgrades = array();
+
+    if ($upgradeall) {
+        $assignmentids = tool_assignmentupgrade_load_all_upgradable_assignmentids();
+    }
+
+    $assignment_upgrader = new assign_upgrade_manager();
+    foreach ($assignmentids as $assignmentid) {
+        $info = tool_assignmentupgrade_get_assignment($assignmentid);
+        if ($info) {
+            $log = '';
+            $success = $assignment_upgrader->upgrade_assignment($assignmentid, $log);
+        } else {
+            $success = false;
+            $log = get_string('assignmentnotfound', 'tool_assignmentupgrade', $assignmentid);
+            $info = new stdClass();
+            $info->name = get_string('unknown', 'tool_assignmentupgrade');
+            $info->shortname = get_string('unknown', 'tool_assignmentupgrade');
+        }
+
+        $upgrades[] = array('assignmentsummary'=>$info, 'success'=>$success, 'log'=>$log);
+    }
+    return $upgrades;
+}
+
+/**
+ * Convert a single assignment from the old format to the new one.
+ * @param stdClass $assignmentinfo An object containing information about this class
+ * @param string $log This gets appended to with the details of the conversion process
+ * @return boolean This is the overall result (true/false)
+ */
+function tool_assignmentupgrade_upgrade_assignment($assignmentinfo, &$log) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    require_once($CFG->dirroot . '/mod/assign/upgradelib.php');
+    $assignment_upgrader = new assign_upgrade_manager();
+    return $assignment_upgrader->upgrade_assignment($assignmentinfo->id, $log);
+}
+
+/**
+ * Get the information about a assignment to be upgraded.
+ * @param int $assignmentid the assignment id.
+ * @return stdClass the information about that assignment.
+ */
+function tool_assignmentupgrade_get_assignment($assignmentid) {
+    global $DB;
+    return $DB->get_record_sql("
+            SELECT a.id, a.name, c.shortname, c.id AS courseid
+            FROM {assignment} a
+            JOIN {course} c ON c.id = a.course
+            WHERE a.id = ?", array($assignmentid));
+}
+
diff --git a/admin/tool/assignmentupgrade/module.js b/admin/tool/assignmentupgrade/module.js
new file mode 100644 (file)
index 0000000..829f99a
--- /dev/null
@@ -0,0 +1,66 @@
+
+M.tool_assignmentupgrade = {
+    init_upgrade_table: function(Y) {
+
+        Y.use('node', function(Y) {
+            checkboxes = Y.all('td.c0 input');
+            checkboxes.each(function(node) {
+                node.on('change', function(e) {
+                    rowelement = e.currentTarget.get('parentNode').get('parentNode');
+                    if (e.currentTarget.get('checked')) {
+                        rowelement.setAttribute('class', 'selectedrow');
+                    } else {
+                        rowelement.setAttribute('class', 'unselectedrow');
+                    }
+                });
+
+                rowelement = node.get('parentNode').get('parentNode');
+                if (node.get('checked')) {
+                    rowelement.setAttribute('class', 'selectedrow');
+                } else {
+                    rowelement.setAttribute('class', 'unselectedrow');
+                }
+            });
+        });
+
+        var selectall = Y.one('th.c0 input');
+        selectall.on('change', function(e) {
+            if (e.currentTarget.get('checked')) {
+                checkboxes = Y.all('td.c0 input');
+                checkboxes.each(function(node) {
+                    rowelement = node.get('parentNode').get('parentNode');
+                    node.set('checked', true);
+                    rowelement.setAttribute('class', 'selectedrow');
+                });
+            } else {
+                checkboxes = Y.all('td.c0 input');
+                checkboxes.each(function(node) {
+                    rowelement = node.get('parentNode').get('parentNode');
+                    node.set('checked', false);
+                    rowelement.setAttribute('class', 'unselectedrow');
+                });
+            }
+        });
+
+        var batchform = Y.one('.tool_assignmentupgrade_batchform form');
+        batchform.on('submit', function(e) {
+            checkboxes = Y.all('td.c0 input');
+            var selectedassignments = [];
+            checkboxes.each(function(node) {
+                if (node.get('checked')) {
+                    selectedassignments[selectedassignments.length] = node.get('value');
+                }
+            });
+
+            operation = Y.one('#id_operation');
+            assignmentsinput = Y.one('input.selectedassignments');
+            assignmentsinput.set('value', selectedassignments.join(','));
+            if (selectedassignments.length == 0) {
+                alert(M.str.assign.noassignmentsselected);
+                e.preventDefault();
+            }
+        });
+
+
+    }
+}
diff --git a/admin/tool/assignmentupgrade/renderer.php b/admin/tool/assignmentupgrade/renderer.php
new file mode 100644 (file)
index 0000000..16c013c
--- /dev/null
@@ -0,0 +1,278 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Defines the renderer for the assignment upgrade helper plugin.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Renderer for the assignment upgrade helper plugin.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_assignmentupgrade_renderer extends plugin_renderer_base {
+
+    /**
+     * Render the index page.
+     * @param string $detected information about what sort of site was detected.
+     * @param array $actions list of actions to show on this page.
+     * @return string html to output.
+     */
+    public function index_page($detected, array $actions) {
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->heading(get_string('pluginname', 'tool_assignmentupgrade'));
+        $output .= $this->box($detected);
+        $output .= html_writer::start_tag('ul');
+        foreach ($actions as $action) {
+            $output .= html_writer::tag('li',
+                    html_writer::link($action->url, $action->name) . ' - ' .
+                    $action->description);
+        }
+        $output .= html_writer::end_tag('ul');
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Render a page that is just a simple message.
+     * @param string $message the message to display.
+     * @return string html to output.
+     */
+    public function simple_message_page($message) {
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->heading($message);
+        $output .= $this->back_to_index();
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Render the confirm batch operation page
+     * @param stdClass $data Submitted form data with list of assignments to upgrade
+     * @return string html to output.
+     */
+    public function confirm_batch_operation_page(stdClass $data) {
+        $output = '';
+        $output .= $this->header();
+
+        $output .= $this->heading(get_string('confirmbatchupgrade', 'tool_assignmentupgrade'));
+        $output .= $this->output->spacer(array(), true);
+
+        $output .= $this->container_start('tool_assignmentupgrade_confirmbatch');
+
+        $output .= $this->render(new tool_assignmentupgrade_batchoperationconfirm($data));
+        $output .= $this->container_end();
+
+        $output .= $this->back_to_index();
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Render the confirm batch continue / cancel links
+     * @param tool_assignmentupgrade_batchoperationconfirm $confirm Wrapper class to determine the continue message and url
+     * @return string html to output.
+     */
+    public function render_tool_assignmentupgrade_batchoperationconfirm(tool_assignmentupgrade_batchoperationconfirm $confirm) {
+        $output = '';
+
+        if ($confirm->continueurl) {
+            $output .= $this->output->confirm($confirm->continuemessage, $confirm->continueurl, tool_assignmentupgrade_url('listnotupgraded'));
+        } else {
+            $output .= $this->output->box($confirm->continuemessage);
+            $output .= $this->output->continue_button(tool_assignmentupgrade_url('listnotupgraded'));
+        }
+        return $output;
+    }
+
+    /**
+     * Render the list of assignments that still need to be upgraded page.
+     * @param tool_assignmentupgrade_assignments_table $assignments of data about assignments.
+     * @param tool_assignmentupgrade_batchoperations_form $batchform Submitted form with list of assignments to upgrade
+     * @return string html to output.
+     */
+    public function assignment_list_page(tool_assignmentupgrade_assignments_table $assignments, tool_assignmentupgrade_batchoperations_form $batchform) {
+        $output = '';
+        $output .= $this->header();
+        $this->page->requires->js_init_call('M.tool_assignmentupgrade.init_upgrade_table', array());
+
+
+        $output .= $this->heading(get_string('notupgradedtitle', 'tool_assignmentupgrade'));
+        $output .= $this->box(get_string('notupgradedintro', 'tool_assignmentupgrade'));
+        $output .= $this->output->spacer(array(), true);
+
+        $output .= $this->container_start('tool_assignmentupgrade_upgradetable');
+
+        $output .= $this->flexible_table($assignments, $assignments->get_rows_per_page(), true);
+        $output .= $this->container_end();
+
+        if ($assignments->anyupgradableassignments) {
+            $output .= $this->container_start('tool_assignmentupgrade_batchform');
+            $output .= $this->moodleform($batchform);
+            $output .= $this->container_end();
+        }
+
+        $output .= $this->back_to_index();
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Render the result of an assignment conversion
+     * @param array $assignments - An array of arrays with keys $entry['assignmentsummary', 'success', 'log']
+     *                            See convert_assignment_result for more description of these keys.
+     * @return string html to output.
+     */
+    public function convert_multiple_assignments_result($assignments) {
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->heading(get_string('batchupgrade', 'tool_assignmentupgrade'));
+
+        foreach ($assignments as $assignment) {
+            $assignmentsummary = $assignment['assignmentsummary'];
+            $success = $assignment['success'];
+            $log = $assignment['log'];
+
+            $output .= $this->heading(get_string('upgradeassignmentsummary', 'tool_assignmentupgrade', $assignmentsummary), 5);
+            if ($success) {
+                $output .= $this->container(get_string('upgradeassignmentsuccess', 'tool_assignmentupgrade'));
+
+            } else {
+                $output .= $this->container(get_string('upgradeassignmentfailed', 'tool_assignmentupgrade', $assignment));
+            }
+            if (isset($assignmentsummary->courseid)) {
+                $output .= html_writer::link(new moodle_url('/course/view.php', array('id'=>$assignmentsummary->courseid)) ,get_string('viewcourse', 'tool_assignmentupgrade'));
+            }
+
+
+        }
+
+        $output .= $this->continue_button(tool_assignmentupgrade_url('listnotupgraded'));
+
+
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Render the result of an assignment conversion
+     * @param stdClass $assignmentsummary data about the assignment to upgrade.
+     * @param bool $success Set to true if the outcome of the conversion was a success
+     * @param string $log The log from the conversion
+     * @return string html to output.
+     */
+    public function convert_assignment_result($assignmentsummary, $success, $log) {
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->heading(get_string('conversioncomplete', 'tool_assignmentupgrade'));
+
+        if (!$success) {
+            $output .= get_string('conversionfailed', 'tool_assignmentupgrade', $log);
+        } else {
+            $output .= html_writer::link(new moodle_url('/course/view.php', array('id'=>$assignmentsummary->courseid)) ,get_string('viewcourse', 'tool_assignmentupgrade'));
+        }
+
+        $output .= $this->continue_button(tool_assignmentupgrade_url('listnotupgraded'));
+
+
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Render the are-you-sure page to confirm a manual upgrade.
+     * @param stdClass $assignmentsummary data about the assignment to upgrade.
+     * @return string html to output.
+     */
+    public function convert_assignment_are_you_sure($assignmentsummary) {
+        $output = '';
+        $output .= $this->header();
+        $output .= $this->heading(get_string('areyousure', 'tool_assignmentupgrade'));
+
+        $params = array('id' => $assignmentsummary->id, 'confirmed' => 1, 'sesskey' => sesskey());
+        $output .= $this->confirm(get_string('areyousuremessage', 'tool_assignmentupgrade', $assignmentsummary),
+                new single_button(tool_assignmentupgrade_url('upgradesingle', $params), get_string('yes')),
+                tool_assignmentupgrade_url('listnotupgraded'));
+
+        $output .= $this->footer();
+        return $output;
+    }
+
+    /**
+     * Helper method dealing with the fact we can not just fetch the output of flexible_table
+     *
+     * @param flexible_table $table
+     * @param int $rowsperpage
+     * @param bool $displaylinks Show links in the table
+     * @return string HTML
+     */
+    protected function flexible_table(flexible_table $table, $rowsperpage, $displaylinks) {
+
+        $o = '';
+        ob_start();
+        $table->out($rowsperpage, $displaylinks);
+        $o = ob_get_contents();
+        ob_end_clean();
+
+        return $o;
+    }
+
+    /**
+     * Helper method dealing with the fact we can not just fetch the output of moodleforms
+     *
+     * @param moodleform $mform
+     * @return string HTML
+     */
+    protected function moodleform(moodleform $mform) {
+
+        $o = '';
+        ob_start();
+        $mform->display();
+        $o = ob_get_contents();
+        ob_end_clean();
+
+        return $o;
+    }
+
+
+    /**
+     * Render a link in a div, such as the 'Back to plugin main page' link.
+     * @param string|moodle_url $url the link URL.
+     * @param string $text the link text.
+     * @return string html to output.
+     */
+    public function end_of_page_link($url, $text) {
+        return html_writer::tag('div', html_writer::link($url, $text), array('class' => 'mdl-align'));
+    }
+
+    /**
+     * Output a link back to the plugin index page.
+     * @return string html to output.
+     */
+    public function back_to_index() {
+        return $this->end_of_page_link(tool_assignmentupgrade_url('index'), get_string('backtoindex', 'tool_assignmentupgrade'));
+    }
+}
diff --git a/admin/tool/assignmentupgrade/settings.php b/admin/tool/assignmentupgrade/settings.php
new file mode 100644 (file)
index 0000000..a637e38
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Adds this plugin to the admin menu.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+if ($hassiteconfig) { // needs this condition or there is error on login page
+    $ADMIN->add('root', new admin_externalpage('assignmentupgrade',
+            get_string('pluginname', 'tool_assignmentupgrade'),
+            new moodle_url('/admin/tool/assignmentupgrade/index.php')));
+}
\ No newline at end of file
diff --git a/admin/tool/assignmentupgrade/styles.css b/admin/tool/assignmentupgrade/styles.css
new file mode 100644 (file)
index 0000000..0188dc4
--- /dev/null
@@ -0,0 +1,11 @@
+#page-admin-tool-assignmentupgrade-listnotupgraded .tool_assignmentupgrade_upgradetable .c0 { display: none; }
+#page-admin-tool-assignmentupgrade-listnotupgraded.jsenabled .tool_assignmentupgrade_upgradetable .c0 { display: table-cell; }
+/*
+.gradingbatchoperationsform { display: none; }
+.jsenabled .gradingbatchoperationsform { display: block; }
+*/
+
+#page-admin-tool-assignmentupgrade-listnotupgraded .tool_assignmentupgrade_upgradetable tr.selectedrow td { background-color: #ffeecc; }
+#page-admin-tool-assignmentupgrade-listnotupgraded .tool_assignmentupgrade_upgradetable tr.unselectedrow td { background-color: white; }
+
+
diff --git a/admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php b/admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php
new file mode 100644 (file)
index 0000000..105530a
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the forms to create and edit an instance of this module
+ *
+ * @package   tool_assignmentupgrade
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
+
+
+/** Include formslib.php */
+require_once ($CFG->libdir.'/formslib.php');
+
+/**
+ * Assignment upgrade batch operations form
+ *
+ * @package   tool_assignmentupgrade
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_assignmentupgrade_batchoperations_form extends moodleform {
+    /**
+     * Define this form - is called from parent constructor
+     */
+    function definition() {
+        $mform = $this->_form;
+        $instance = $this->_customdata;
+
+        $mform->addElement('header', 'general', get_string('batchoperations', 'tool_assignmentupgrade'));
+        // visible elements
+        $mform->addElement('hidden', 'selectedassignments', '', array('class'=>'selectedassignments'));
+
+        $mform->addElement('submit', 'upgradeselected', get_string('upgradeselected', 'tool_assignmentupgrade'));
+        $mform->addElement('submit', 'upgradeall', get_string('upgradeall', 'tool_assignmentupgrade'));
+    }
+
+}
+
diff --git a/admin/tool/assignmentupgrade/upgradableassignmentstable.php b/admin/tool/assignmentupgrade/upgradableassignmentstable.php
new file mode 100644 (file)
index 0000000..ed830f6
--- /dev/null
@@ -0,0 +1,172 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the definition for the grading table which subclassses easy_table
+ *
+ * @package   tool_assignmentupgrade
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/gradelib.php');
+require_once($CFG->dirroot.'/mod/assign/locallib.php');
+
+/**
+ * Extends table_sql to provide a table of assignment submissions
+ *
+ * @package   tool_assignmentupgrade
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class tool_assignmentupgrade_assignments_table extends table_sql implements renderable {
+    /** @var int $perpage */
+    private $perpage = 10;
+    /** @var int $rownum (global index of current row in table) */
+    private $rownum = -1;
+    /** @var renderer_base for getting output */
+    private $output = null;
+    /** @var boolean anyupgradableassignments - True if there is one or more assignments that can upgraded */
+    public $anyupgradableassignments = false;
+
+    /**
+     * This table loads a list of the old assignment instances and tests them to see if they can be upgraded
+     *
+     * @param int $perpage How many per page
+     * @param int $rowoffset The starting row for pagination
+     */
+    function __construct($perpage, $rowoffset=0) {
+        global $PAGE;
+        parent::__construct('tool_assignmentupgrade_assignments');
+        $this->perpage = $perpage;
+        $this->output = $PAGE->get_renderer('tool_assignmentupgrade');
+
+        $this->define_baseurl(new moodle_url('/admin/tool/assignmentupgrade/listnotupgraded.php'));
+
+        $this->anyupgradableassignments = tool_assignmentupgrade_any_upgradable_assignments();
+
+        // do some business - then set the sql
+        if ($rowoffset) {
+            $this->rownum = $rowoffset - 1;
+        }
+
+        $fields = 'a.id as id, a.name as name, a.assignmenttype as type, c.shortname as courseshortname, c.id as courseid, COUNT(s.id) as submissioncount';
+        $from = '{assignment} a JOIN {course} c ON a.course = c.id ' .
+                        ' LEFT JOIN {assignment_submissions} s ON a.id = s.assignment';
+
+
+        $where = '1 = 1';
+        $where .= ' GROUP BY a.id, a.name, a.assignmenttype, c.shortname, c.id ';
+
+        $this->set_sql($fields, $from, $where, array());
+        $this->set_count_sql('SELECT COUNT(*) FROM ' . $from, array());
+
+        $columns = array();
+        $headers = array();
+
+        $columns[] = 'select';
+        $headers[] = get_string('select', 'tool_assignmentupgrade') . '<div class="selectall"><input type="checkbox" name="selectall" title="' . get_string('selectall') . '"/></div>';
+        $columns[] = 'upgradable';
+        $headers[] = get_string('upgradable', 'tool_assignmentupgrade');
+        $columns[] = 'id';
+        $headers[] = get_string('assignmentid', 'tool_assignmentupgrade');
+        $columns[] = 'courseshortname';
+        $headers[] = get_string('course');
+        $columns[] = 'name';
+        $headers[] = get_string('name');
+        $columns[] = 'type';
+        $headers[] = get_string('assignmenttype', 'tool_assignmentupgrade');
+        $columns[] = 'submissioncount';
+        $headers[] = get_string('submissions', 'tool_assignmentupgrade');
+
+        // set the columns
+        $this->define_columns($columns);
+        $this->define_headers($headers);
+        $this->no_sorting('upgradable');
+        $this->no_sorting('select');
+    }
+
+    /**
+     * Return the number of rows to display on a single page
+     *
+     * @return int The number of rows per page
+     */
+    function get_rows_per_page() {
+        return $this->perpage;
+    }
+
+    /**
+     * Format a link to the assignment instance
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_name(stdClass $row) {
+        return html_writer::link(new moodle_url('/mod/assignment/view.php',
+                array('a' => $row->id)), $row->name);
+    }
+
+
+    /**
+     * Format a link to the upgrade single tool
+     *
+     * @param stdClass $row (contains cached result from previous upgradable check)
+     * @return string
+     */
+    function col_upgradable(stdClass $row) {
+        if ($row->upgradable) {
+            return html_writer::link(new moodle_url('/admin/tool/assignmentupgrade/upgradesingleconfirm.php',
+                    array('id' => $row->id)), get_string('supported', 'tool_assignmentupgrade'));
+        } else {
+            return get_string('notsupported', 'tool_assignmentupgrade');
+        }
+    }
+
+    /**
+     * Insert a checkbox for selecting the current row for batch operations
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_select(stdClass $row) {
+        global $CFG;
+        $version = get_config('assignment_' . $row->type, 'version');
+        require_once($CFG->dirroot . '/mod/assign/locallib.php');
+        if (assign::can_upgrade_assignment($row->type, $version)) {
+            $row->upgradable = true;
+            return '<input type="checkbox" name="selectedassignment" value="' . $row->id . '"/>';
+        }
+        $row->upgradable = false;
+        return '';
+    }
+
+    /**
+     * Override the table show_hide_link to not show for select column
+     *
+     * @param string $column the column name, index into various names.
+     * @param int $index numerical index of the column.
+     * @return string HTML fragment.
+     */
+    protected function show_hide_link($column, $index) {
+        if ($index > 0) {
+            return parent::show_hide_link($column, $index);
+        }
+        return '';
+    }
+}
diff --git a/admin/tool/assignmentupgrade/upgradesingle.php b/admin/tool/assignmentupgrade/upgradesingle.php
new file mode 100644 (file)
index 0000000..8ae2aab
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Script to show all the assignments that have not been upgraded after the main upgrade.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(dirname(__FILE__) . '/../../../config.php');
+require_once(dirname(__FILE__) . '/locallib.php');
+require_once($CFG->libdir . '/adminlib.php');
+
+$assignmentid = required_param('id', PARAM_INT);
+
+// admin_externalpage_setup calls require_login and checks moodle/site:config
+admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('upgradesingle', array('id' => $assignmentid)));
+
+$PAGE->navbar->add(get_string('upgradesingle', 'tool_assignmentupgrade'));
+$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
+
+$assignmentinfo = tool_assignmentupgrade_get_assignment($assignmentid);
+if (!$assignmentinfo) {
+    print_error('invalidrequest');
+    die();
+}
+
+$log = '';
+$result = tool_assignmentupgrade_upgrade_assignment($assignmentinfo, $log);
+
+echo $renderer->convert_assignment_result($assignmentinfo, $result, $log);
diff --git a/admin/tool/assignmentupgrade/upgradesingleconfirm.php b/admin/tool/assignmentupgrade/upgradesingleconfirm.php
new file mode 100644 (file)
index 0000000..015d217
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Script to show all the assignments that have not been upgraded after the main upgrade.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once(dirname(__FILE__) . '/../../../config.php');
+require_once(dirname(__FILE__) . '/locallib.php');
+require_once($CFG->libdir . '/adminlib.php');
+
+$assignmentid = required_param('id', PARAM_INT);
+
+// admin_externalpage_setup calls require_login and checks moodle/site:config
+admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('upgradesingle', array('id' => $assignmentid)));
+
+$PAGE->navbar->add(get_string('upgradesingle', 'tool_assignmentupgrade'));
+$renderer = $PAGE->get_renderer('tool_assignmentupgrade');
+
+$assignmentinfo = tool_assignmentupgrade_get_assignment($assignmentid);
+
+echo $renderer->convert_assignment_are_you_sure($assignmentinfo);
diff --git a/admin/tool/assignmentupgrade/version.php b/admin/tool/assignmentupgrade/version.php
new file mode 100644 (file)
index 0000000..6441ffd
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Version details.
+ *
+ * @package    tool_assignmentupgrade
+ * @copyright  2012 NetSpot
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$plugin->version   = 2012021700;
+$plugin->requires  = 2011092100;
+$plugin->component = 'tool_assignmentupgrade';
\ No newline at end of file
diff --git a/mod/assign/adminlib.php b/mod/assign/adminlib.php
new file mode 100644 (file)
index 0000000..62c24f3
--- /dev/null
@@ -0,0 +1,480 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the classes for the admin settings of the assign module.
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/** Include adminlib.php */
+require_once($CFG->libdir . '/adminlib.php');
+
+/**
+ * Admin external page that displays a list of the installed submission plugins.
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class assign_admin_page_manage_assign_plugins extends admin_externalpage {
+
+    /** @var string the name of plugin subtype */
+    private $subtype = '';
+
+    /**
+     * The constructor - calls parent constructor
+     *
+     * @param string $subtype
+     */
+    public function __construct($subtype) {
+        $this->subtype = $subtype;
+        parent::__construct('manage' . $subtype . 'plugins', get_string('manage' . $subtype . 'plugins', 'assign'),
+                new moodle_url('/mod/assign/adminmanageplugins.php', array('subtype'=>$subtype)));
+    }
+
+    /**
+     * Search plugins for the specified string
+     *
+     * @param string $query The string to search for
+     * @return array
+     */
+    public function search($query) {
+        if ($result = parent::search($query)) {
+            return $result;
+        }
+
+        $found = false;
+        $textlib = new textlib();
+
+        foreach (get_plugin_list($this->subtype) as $name => $notused) {
+            if (strpos($textlib::strtolower(get_string('pluginname', $this->subtype . '_' . $name)),
+                    $query) !== false) {
+                $found = true;
+                break;
+            }
+        }
+        if ($found) {
+            $result = new stdClass();
+            $result->page     = $this;
+            $result->settings = array();
+            return array($this->name => $result);
+        } else {
+            return array();
+        }
+    }
+}
+
+
+/**
+ * Class that handles the display and configuration of the list of submission plugins.
+ *
+ * @package   mod_assign
+ * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class assign_plugin_manager {
+
+    /** @var object the url of the manage submission plugin page */
+    private $pageurl;
+    /** @var string any error from the current action */
+    private $error = '';
+    /** @var string either submission or feedback */
+    private $subtype = '';
+
+    /**
+     * Constructor for this assignment plugin manager
+     * @param string $subtype - either assignsubmission or assignfeedback
+     */
+    public function __construct($subtype) {
+        $this->pageurl = new moodle_url('/mod/assign/adminmanageplugins.php', array('subtype'=>$subtype));
+        $this->subtype = $subtype;
+    }
+
+
+    /**
+     * Return a list of plugins sorted by the order defined in the admin interface
+     *
+     * @return array The list of plugins
+     */
+    public function get_sorted_plugins_list() {
+        $names = get_plugin_list($this->subtype);
+
+        $result = array();
+
+        foreach ($names as $name => $path) {
+            $idx = get_config($this->subtype . '_' . $name, 'sortorder');
+            if (!$idx) {
+                $idx = 0;
+            }
+            while (array_key_exists($idx, $result)) $idx +=1;
+            $result[$idx] = $name;
+        }
+        ksort($result);
+
+        return $result;
+    }
+
+
+    /**
+     * Util function for writing an action icon link
+     *
+     * @param string $action URL parameter to include in the link
+     * @param string $plugintype URL parameter to include in the link
+     * @param string $icon The key to the icon to use (e.g. 't/up')
+     * @param string $alt The string description of the link used as the title and alt text
+     * @return string The icon/link
+     */
+    private function format_icon_link($action, $plugintype, $icon, $alt) {
+        global $OUTPUT;
+
+        return $OUTPUT->action_icon(new moodle_url($this->pageurl,
+                array('action' => $action, 'plugin'=> $plugintype, 'sesskey' => sesskey())),
+                new pix_icon($icon, $alt, 'moodle', array('title' => $alt)),
+                null, array('title' => $alt)) . ' ';
+    }
+
+    /**
+     * Write the HTML for the submission plugins table.
+     *
+     * @return None
+     */
+    private function view_plugins_table() {
+        global $OUTPUT, $CFG;
+        /** Include tablelib.php */
+        require_once($CFG->libdir . '/tablelib.php');
+
+        // Set up the table.
+        $this->view_header();
+        $table = new flexible_table($this->subtype . 'pluginsadminttable');
+        $table->define_baseurl($this->pageurl);
+        $table->define_columns(array('pluginname', 'version', 'hideshow', 'order',
+                'delete', 'settings'));
+        $table->define_headers(array(get_string($this->subtype . 'pluginname', 'assign'),
+                get_string('version'), get_string('hideshow', 'assign'),
+                get_string('order'), get_string('delete'), get_string('settings')));
+        $table->set_attribute('id', $this->subtype . 'plugins');
+        $table->set_attribute('class', 'generaltable generalbox boxaligncenter boxwidthwide');
+        $table->setup();
+
+
+        $plugins = $this->get_sorted_plugins_list();
+        $shortsubtype = substr($this->subtype, strlen('assign'));
+
+        foreach ($plugins as $idx => $plugin) {
+            $row = array();
+
+            $row[] = get_string('pluginname', $this->subtype . '_' . $plugin);
+            $row[] = get_config($this->subtype . '_' . $plugin, 'version');
+
+            $visible = !get_config($this->subtype . '_' . $plugin, 'disabled');
+
+            if ($visible) {
+                $row[] = $this->format_icon_link('hide', $plugin, 'i/hide', get_string('disable'));
+            } else {
+                $row[] = $this->format_icon_link('show', $plugin, 'i/show', get_string('enable'));
+            }
+
+            $movelinks = '';
+            if (!$idx == 0) {
+                $movelinks .= $this->format_icon_link('moveup', $plugin, 't/up', get_string('up'));
+            } else {
+                $movelinks .= $OUTPUT->spacer(array('width'=>15));
+            }
+            if ($idx != count($plugins) - 1) {
+                $movelinks .= $this->format_icon_link('movedown', $plugin, 't/down', get_string('down'));
+            }
+            $row[] = $movelinks;
+
+            if ($row[1] != '') {
+                $row[] = $this->format_icon_link('delete', $plugin, 't/delete', get_string('delete'));
+            } else {
+                $row[] = '&nbsp;';
+            }
+            if ($row[1] != '' && file_exists($CFG->dirroot . '/mod/assign/' . $shortsubtype . '/' . $plugin . '/settings.php')) {
+                $row[] = html_writer::link(new moodle_url('/admin/settings.php',
+                        array('section' => $this->subtype . '_' . $plugin)), get_string('settings'));
+            } else {
+                $row[] = '&nbsp;';
+            }
+            $table->add_data($row);
+        }
+
+
+        $table->finish_output();
+        $this->view_footer();
+    }
+
+    /**
+     * Write the page header
+     *
+     * @return None
+     */
+    private function view_header() {
+        global $OUTPUT;
+        admin_externalpage_setup('manage' . $this->subtype . 'plugins');
+        // Print the page heading.
+        echo $OUTPUT->header();
+        echo $OUTPUT->heading(get_string('manage' . $this->subtype . 'plugins', 'assign'));
+    }
+
+    /**
+     * Write the page footer
+     *
+     * @return None
+     */
+    private function view_footer() {
+        global $OUTPUT;
+        echo $OUTPUT->footer();
+    }
+
+    /**
+     * Check this user has permission to edit the list of installed plugins
+     *
+     * @return None
+     */
+    private function check_permissions() {
+        // Check permissions.
+        require_login();
+        $systemcontext = context_system::instance();
+        require_capability('moodle/site:config', $systemcontext);
+    }
+
+    /**
+     * Delete the database and files associated with this plugin.
+     *
+     * @param string $plugin - The type of the plugin to delete
+     * @return string the name of the next page to display
+     */
+    public function delete_plugin($plugin) {
+        global $CFG, $DB, $OUTPUT;
+        $confirm = optional_param('confirm', null, PARAM_BOOL);
+
+        if ($confirm) {
+            // Delete any configuration records.
+            if (!unset_all_config_for_plugin('assignsubmission_' . $plugin)) {
+                $this->error = $OUTPUT->notification(get_string('errordeletingconfig', 'admin', $this->subtype . '_' . $plugin));
+            }
+
+
+            // Should be covered by the previous function - but just in case
+            unset_config('disabled', $this->subtype . '_' . $plugin);
+            unset_config('sortorder', $this->subtype . '_' . $plugin);
+
+            // delete the plugin specific config settings
+            $DB->delete_records('assign_plugin_config', array('plugin'=>$plugin, 'subtype'=>$this->subtype));
+
+            // Then the tables themselves
+            drop_plugin_tables($this->subtype . '_' . $plugin, $CFG->dirroot . '/mod/assign/' . $this->subtype . '/' .$plugin. '/db/install.xml', false);
+
+            // Remove event handlers and dequeue pending events
+            events_uninstall($this->subtype . '_' . $plugin);
+
+            // the page to display
+            return 'plugindeleted';
+        } else {
+            // the page to display
+            return 'confirmdelete';
+        }
+
+    }
+
+    /**
+     * Show the page that gives the details of the plugin that was just deleted
+     *
+     * @param string $plugin - The plugin that was just deleted
+     * @return None
+     */
+    private function view_plugin_deleted($plugin) {
+        global $OUTPUT;
+        $this->view_header();
+        echo $OUTPUT->heading(get_string('deletingplugin', 'assign', get_string('pluginname', $this->subtype . '_' . $plugin)));
+        echo $this->error;
+        echo $OUTPUT->notification(get_string('plugindeletefiles', 'moodle', array('name'=>get_string('pluginname', $this->subtype . '_' . $plugin), 'directory'=>('/mod/assign/' . $this->subtype . '/'.$plugin))));
+        echo $OUTPUT->continue_button($this->pageurl);
+        $this->view_footer();
+    }
+
+    /**
+     * Show the page that asks the user to confirm they want to delete a plugin
+     *
+     * @param string $plugin - The plugin that will be deleted
+     * @return None
+     */
+    private function view_confirm_delete($plugin) {
+        global $OUTPUT;
+        $this->view_header();
+        echo $OUTPUT->heading(get_string('deletepluginareyousure', 'assign', get_string('pluginname', $this->subtype . '_' . $plugin)));
+        echo $OUTPUT->confirm(get_string('deletepluginareyousuremessage', 'assign', get_string('pluginname', $this->subtype . '_' . $plugin)),
+                new moodle_url($this->pageurl, array('action' => 'delete', 'plugin'=>$plugin, 'confirm' => 1)),
+                $this->pageurl);
+        $this->view_footer();
+    }
+
+
+
+    /**
+     * Hide this plugin
+     *
+     * @param string $plugin - The plugin to hide
+     * @return string The next page to display
+     */
+    public function hide_plugin($plugin) {
+        set_config('disabled', 1, $this->subtype . '_' . $plugin);
+        return 'view';
+    }
+
+    /**
+     * Change the order of this plugin
+     *
+     * @param string $plugintomove - The plugin to move
+     * @param string $dir - up or down
+     * @return string The next page to display
+     */
+    public function move_plugin($plugintomove, $dir) {
+        // get a list of the current plugins
+        $plugins = $this->get_sorted_plugins_list();
+
+        $currentindex = 0;
+
+        // throw away the keys
+
+        $plugins = array_values($plugins);
+
+        // find this plugin in the list
+        foreach ($plugins as $key => $plugin) {
+            if ($plugin == $plugintomove) {
+                $currentindex = $key;
+                break;
+            }
+        }
+
+        // make the switch
+        if ($dir == 'up') {
+            if ($currentindex > 0) {
+                $tempplugin = $plugins[$currentindex - 1];
+                $plugins[$currentindex - 1] = $plugins[$currentindex];
+                $plugins[$currentindex] = $tempplugin;
+            }
+        } else if ($dir == 'down') {
+            if ($currentindex < (count($plugins) - 1)) {
+                $tempplugin = $plugins[$currentindex + 1];
+                $plugins[$currentindex + 1] = $plugins[$currentindex];
+                $plugins[$currentindex] = $tempplugin;
+            }
+        }
+
+        // save the new normal order
+        foreach ($plugins as $key => $plugin) {
+            set_config('sortorder', $key, $this->subtype . '_' . $plugin);
+        }
+        return 'view';
+    }
+
+
+    /**
+     * Show this plugin
+     *
+     * @param string $plugin - The plugin to show
+     * @return string The next page to display
+     */
+    public function show_plugin($plugin) {
+        set_config('disabled', 0, $this->subtype . '_' . $plugin);
+        return 'view';
+    }
+
+
+    /**
+     * This is the entry point for this controller class
+     *
+     * @param string $action - The action to perform
+     * @param string $plugin - Optional name of a plugin type to perform the action on
+     * @return None
+     */
+    public function execute($action, $plugin) {
+        if ($action == null) {
+            $action = 'view';
+        }
+
+        $this->check_permissions();
+
+        // process
+        if ($action == 'delete' && $plugin != null) {
+            $action = $this->delete_plugin($plugin);
+        } else if ($action == 'hide' && $plugin != null) {
+            $action = $this->hide_plugin($plugin);
+        } else if ($action == 'show' && $plugin != null) {
+            $action = $this->show_plugin($plugin);
+        } else if ($action == 'moveup' && $plugin != null) {
+            $action = $this->move_plugin($plugin, 'up');
+        } else if ($action == 'movedown' && $plugin != null) {
+            $action = $this->move_plugin($plugin, 'down');
+        }
+
+
+        // view
+        if ($action == 'confirmdelete' && $plugin != null) {
+            $this->view_confirm_delete($plugin);
+        } else if ($action == 'plugindeleted' && $plugin != null) {
+            $this->view_plugin_deleted($plugin);
+        } else if ($action == 'view') {
+            $this->view_plugins_table();
+        }
+    }
+
+    /**
+     * This function adds plugin pages to the navigation menu
+     *
+     * @static
+     * @param string $subtype - The type of plugin (submission or feedback)
+     * @param part_of_admin_tree $admin - The handle to the admin menu
+     * @param admin_settingpage $settings - The handle to current node in the navigation tree
+     * @param stdClass $module - The handle to the current module
+     * @return None
+     */
+    static function add_admin_assign_plugin_settings($subtype, part_of_admin_tree $admin, admin_settingpage $settings, stdClass $module) {
+        global $CFG;
+
+        $plugins = get_plugin_list_with_file($subtype, 'settings.php', false);
+        $pluginsbyname = array();
+        foreach ($plugins as $plugin => $plugindir) {
+            $pluginname = get_string('pluginname', $subtype . '_'.$plugin);
+            $pluginsbyname[$pluginname] = $plugin;
+        }
+        ksort($pluginsbyname);
+
+        // We need to reset settings after the loop
+        $tempsettings = $settings;
+        foreach ($pluginsbyname as $pluginname => $plugin) {
+            $settings = new admin_settingpage($subtype . '_'.$plugin,
+                    $pluginname, 'moodle/site:config', !$module->visible);
+            if ($admin->fulltree) {
+                $shortsubtype = substr($subtype, strlen('assign'));
+                include($CFG->dirroot . "/mod/assign/$shortsubtype/$plugin/settings.php");
+            }
+
+            $admin->add($subtype . 'plugins', $settings);
+        }
+
+        // Reset settings to the original point in the tree
+        $settings = $tempsettings;
+
+    }
+}
diff --git a/mod/assign/adminmanageplugins.php b/mod/assign/adminmanageplugins.php
new file mode 100644 (file)
index 0000000..54a6ef3
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Allows the admin to manage assignment plugins
+ *
+ * @package    mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/** Include config.php */
+require_once(dirname(__FILE__) . '/../../config.php');
+/** Include adminlib.php */
+require_once($CFG->dirroot.'/mod/assign/adminlib.php');
+
+// create the class for this controller
+$pluginmanager = new assign_plugin_manager(required_param('subtype', PARAM_PLUGIN));
+
+$PAGE->set_context(get_system_context());
+
+// execute the controller
+$pluginmanager->execute(optional_param('action', null, PARAM_PLUGIN), optional_param('plugin', null, PARAM_PLUGIN));
diff --git a/mod/assign/assignmentplugin.php b/mod/assign/assignmentplugin.php
new file mode 100644 (file)
index 0000000..19382b9
--- /dev/null
@@ -0,0 +1,525 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the functions for assign_plugin abstract class
+ *
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Abstract class for assign_plugin (submission/feedback).
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class assign_plugin {
+
+    /** @var assign $assignment the assignment record that contains the global settings for this assign instance */
+    protected $assignment;
+    /** @var string $type assignment plugin type */
+    private $type = '';
+    /** @var string $error error message */
+    private $error = '';
+
+
+    /**
+     * Constructor for the abstract plugin type class
+     *
+     * @param assign $assignment
+     * @param string $type
+     */
+    public final function __construct(assign $assignment, $type) {
+        $this->assignment = $assignment;
+        $this->type = $type;
+    }
+
+    /**
+     * Is this the first plugin in the list?
+     *
+     * @return bool
+     */
+    public final function is_first() {
+        $order = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
+
+        if ($order == 0) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Is this the last plugin in the list?
+     *
+     * @return bool
+     */
+    public final function is_last() {
+        if ((count(get_plugin_list($this->get_subtype()))-1) == get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder')) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * This function should be overridden to provide an array of elements that can be added to a moodle
+     * form for display in the settings page for the assignment.
+     * @param MoodleQuickForm $mform The form to add the elements to
+     * @return $array
+     */
+    public function get_settings(MoodleQuickForm $mform) {
+        return;
+    }
+
+    /**
+     * Allows the plugin to update the defaultvalues passed in to
+     * the settings form (needed to set up draft areas for editor
+     * and filemanager elements)
+     * @param array $defaultvalues
+     */
+    public function data_preprocessing(&$defaultvalues) {
+        return;
+    }
+
+    /**
+     * The assignment subtype is responsible for saving it's own settings as the database table for the
+     * standard type cannot be modified.
+     *
+     * @param stdClass $formdata - the data submitted from the form
+     * @return bool - on error the subtype should call set_error and return false.
+     */
+    public function save_settings(stdClass $formdata) {
+        return true;
+    }
+
+    /**
+     * Save the error message from the last error
+     *
+     * @param string $msg - the error description
+     */
+    protected final function set_error($msg) {
+        $this->error = $msg;
+    }
+
+    /**
+     * What was the last error?
+     *
+     *
+     * @return string
+     */
+    public final function get_error() {
+        return $this->error;
+    }
+
+    /**
+     * Should return the name of this plugin type.
+     *
+     * @return string - the name
+     */
+    public abstract function get_name();
+
+    /**
+     * Should return the subtype of this plugin.
+     *
+     * @return string - either 'assignsubmission' or 'feedback'
+     */
+    public abstract function get_subtype();
+
+    /**
+     * Should return the type of this plugin.
+     *
+     * @return string - the type
+     */
+    public final function get_type() {
+        return $this->type;
+    }
+
+    /**
+     * Get the installed version of this plugin
+     *
+     * @return string
+     */
+    public final function get_version() {
+        $version = get_config($this->get_subtype() . '_' . $this->get_type(), 'version');
+        if ($version) {
+            return $version;
+        } else {
+            return '';
+        }
+    }
+
+    /**
+     * Get the required moodle version for this plugin
+     *
+     * @return string
+     */
+    public final function get_requires() {
+        $requires = get_config($this->get_subtype() . '_' . $this->get_type(), 'requires');
+        if ($requires) {
+            return $requires;
+        } else {
+            return '';
+        }
+    }
+
+    /**
+     * Save any custom data for this form submission
+     *
+     * @param stdClass $submissionorgrade - assign_submission or assign_grade
+     *              For submission plugins this is the submission data, for feedback plugins it is the grade data
+     * @param stdClass $data - the data submitted from the form
+     * @return bool - on error the subtype should call set_error and return false.
+     */
+    public function save(stdClass $submissionorgrade, stdClass $data) {
+        return true;
+    }
+
+    /**
+     * Set this plugin to enabled
+     *
+     * @return bool
+     */
+    public final function enable() {
+        return $this->set_config('enabled', 1);
+    }
+
+    /**
+     * Set this plugin to disabled
+     *
+     * @return bool
+     */
+    public final function disable() {
+        return $this->set_config('enabled', 0);
+    }
+
+    /**
+     * Allows hiding this plugin from the submission/feedback screen if it is not enabled.
+     *
+     * @return bool - if false - this plugin will not accept submissions / feedback
+     */
+    public final function is_enabled() {
+        return $this->get_config('enabled');
+    }
+
+    /**
+     * Get any additional fields for the submission/grading form for this assignment.
+     *
+     * @param mixed $submissionorgrade submission|grade - For submission plugins this is the submission data, for feedback plugins it is the grade data
+     * @param MoodleQuickForm $mform - This is the form
+     * @param stdClass $data - This is the form data that can be modified for example by a filemanager element
+     * @return boolean - true if we added anything to the form
+     */
+    public function get_form_elements($submissionorgrade, MoodleQuickForm $mform, stdClass $data) {
+        return false;
+    }
+
+    /**
+     * Should not output anything - return the result as a string so it can be consumed by webservices.
+     *
+     * @param stdClass $submissionorgrade assign_submission or assign_grade 
+     *                 For submission plugins this is the submission data, for feedback plugins it is the grade data
+     * @return string - return a string representation of the submission in full
+     */
+    public function view(stdClass $submissionorgrade) {
+        return '';
+    }
+
+    /**
+     * Get the numerical sort order for this plugin
+     *
+     * @return int
+     */
+    public final function get_sort_order() {
+        $order = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
+        return $order?$order:0;
+    }
+
+    /**
+     * Is this plugin enaled?
+     *
+     * @return bool
+     */
+    public final function is_visible() {
+        $disabled = get_config($this->get_subtype() . '_' . $this->get_type(), 'disabled');
+        return !$disabled;
+    }
+
+
+    /**
+     * Has this plugin got a custom settings.php file?
+     *
+     * @return bool
+     */
+    public final function has_admin_settings() {
+        global $CFG;
+
+        return file_exists($CFG->dirroot . '/mod/assign/' . substr($this->get_subtype(), strlen('assign')) . '/' . $this->get_type() . '/settings.php');
+    }
+
+    /**
+     * Set a configuration value for this plugin
+     *
+     * @param string $name The config key
+     * @param string $value The config value
+     * @return bool
+     */
+    public final function set_config($name, $value) {
+        global $DB;
+
+        $current = $DB->get_record('assign_plugin_config', array('assignment'=>$this->assignment->get_instance()->id, 'subtype'=>$this->get_subtype(), 'plugin'=>$this->get_type(), 'name'=>$name), '*', IGNORE_MISSING);
+
+        if ($current) {
+            $current->value = $value;
+            return $DB->update_record('assign_plugin_config', $current, array('id'=>$current->id));
+        } else {
+            $setting = new stdClass();
+            $setting->assignment = $this->assignment->get_instance()->id;
+            $setting->subtype = $this->get_subtype();
+            $setting->plugin = $this->get_type();
+            $setting->name = $name;
+            $setting->value = $value;
+
+            return $DB->insert_record('assign_plugin_config', $setting) > 0;
+        }
+    }
+
+    /**
+     * Get a configuration value for this plugin
+     *
+     * @param mixed $setting The config key (string) or null
+     * @return mixed string | false
+     */
+    public final function get_config($setting = null) {
+        global $DB;
+
+        if ($setting) {
+            if (!$this->assignment->has_instance()) {
+                return false;
+            }
+            $assignment = $this->assignment->get_instance();
+            if ($assignment) {
+                $result = $DB->get_record('assign_plugin_config', array('assignment'=>$assignment->id, 'subtype'=>$this->get_subtype(), 'plugin'=>$this->get_type(), 'name'=>$setting), '*', IGNORE_MISSING);
+                if ($result) {
+                    return $result->value;
+                }
+            }
+            return false;
+        }
+        $results = $DB->get_records('assign_plugin_config', array('assignment'=>$this->assignment->get_instance()->id, 'subtype'=>$this->get_subtype(), 'plugin'=>$this->get_type()));
+
+        $config = new stdClass();
+        if (is_array($results)) {
+            foreach ($results as $setting) {
+                $name = $setting->name;
+                $config->$name = $setting->value;
+            }
+        }
+        return $config;
+    }
+
+    /**
+     * Should not output anything - return the result as a string so it can be consumed by webservices.
+     *
+     * @param stdClass $submissionorgrade assign_submission or assign_grade 
+     *                 For submission plugins this is the submission data, for feedback plugins it is the grade data
+     * @param bool $showviewlink Modifed to return whether or not to show a link to the full submission/feedback
+     * @return string - return a string representation of the submission in full
+     */
+    public function view_summary(stdClass $submissionorgrade, $showviewlink) {
+        return '';
+    }
+
+    /**
+     * Given a field name, should return the text of an editor field that is part of
+     * this plugin. This is used when exporting to portfolio.
+     *
+     * @param string $name Name of the field.
+     * @param int $submissionid The id of the submission
+     * @return string - The text for the editor field
+     */
+    public function get_editor_text($name, $submissionid) {
+        return '';
+    }
+
+    /**
+     * Produce a list of files suitable for export that represent this feedback or submission
+     *
+     * @param stdClass $submissionorgrade assign_submission or assign_grade 
+     *                 For submission plugins this is the submission data, for feedback plugins it is the grade data
+     * @return array - return an array of files indexed by filename
+     */
+    public function get_files(stdClass $submissionorgrade) {
+        return array();
+    }
+
+     /**
+     * Given a field name, should return the format of an editor field that is part of
+     * this plugin. This is used when exporting to portfolio.
+     *
+     * @param string $name Name of the field.
+     * @param int $submissionid The id of the submission
+     * @return int - The format for the editor field
+     */
+    public function get_editor_format($name, $submissionid) {
+        return 0;
+    }
+
+     /**
+     * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
+     * and version.
+     *
+     * @param string $type The old assignment subtype
+     * @param int $version The old assignment version
+     * @return bool True if upgrade is possible
+     */
+    public function can_upgrade($type, $version) {
+        return false;
+    }
+
+     /**
+     * Upgrade the settings from the old assignment to the new one
+     *
+     * @param context $oldcontext The context for the old assignment module
+     * @param stdClass $oldassignment The data record for the old assignment
+     * @param string $log Record upgrade messages in the log
+     * @return bool true or false - false will trigger a rollback
+     */
+    public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
+        $log = $log . ' ' . get_string('upgradenotimplemented', 'mod_assign', array('type'=>$this->type, 'subtype'=>$this->get_subtype()));
+        return false;
+    }
+
+    /**
+     * Upgrade the submission from the old assignment to the new one
+     *
+     * @param context $oldcontext The data record for the old context
+     * @param stdClass $oldassignment The data record for the old assignment
+     * @param stdClass $oldsubmissionorgrade The data record for the old submission
+     * @param stdClass $submissionorgrade assign_submission or assign_grade The new submission or grade
+     * @param string $log Record upgrade messages in the log
+     * @return boolean true or false - false will trigger a rollback
+     */
+    public function upgrade(context $oldcontext, stdClass $oldassignment, stdClass $oldsubmissionorgrade, stdClass $submissionorgrade, & $log) {
+        $log = $log . ' ' . get_string('upgradenotimplemented', 'mod_assign', array('type'=>$this->type, 'subtype'=>$this->get_subtype()));
+        return false;
+    }
+
+    /**
+     * Formatting for log info
+     * 
+     * @param stdClass $submissionorgrade assign_submission or assign_grade The new submission or grade
+     * @return string
+     */
+    public function format_for_log(stdClass $submissionorgrade) {
+        // format the info for each submission plugin add_to_log
+        return '';
+    }
+
+    /**
+     * The assignment has been deleted - remove the plugin specific data
+     *
+     * @return bool
+     */
+    public function delete_instance() {
+        return true;
+    }
+
+    /**
+     * Run cron for this plugin
+     */
+    public static function cron() {
+    }
+
+    /**
+     * Is this assignment plugin empty? (ie no submission or feedback)
+     * @param stdClass $submissionorgrade assign_submission or assign_grade
+     * @return bool
+     */
+    public function is_empty(stdClass $submissionorgrade) {
+        return true;
+    }
+
+    /**
+     * Get file areas returns a list of areas this plugin stores files
+     * @return array - An array of fileareas (keys) and descriptions (values)
+     */
+    public function get_file_areas() {
+        return array();
+    }
+
+
+    /**
+     * Default implementation of file_get_info for plugins.
+     * This is used by the filebrowser to browse a plugins file areas.
+     *
+     * This implementation should work for most plugins but can be overridden if required.
+     * @param file_browser $browser
+     * @param string $filearea
+     * @param int $itemid
+     * @param string $filepath
+     * @param string $filename
+     * @return file_info_stored
+     */
+    public function get_file_info($browser, $filearea, $itemid, $filepath, $filename) {
+        global $CFG, $DB, $USER;
+        $urlbase = $CFG->wwwroot.'/pluginfile.php';
+
+        // permission check on the itemid
+
+        if ($this->get_subtype() == 'assignsubmission') {
+            if ($itemid) {
+                $record = $DB->get_record('assign_submission', array('id'=>$itemid), 'userid', IGNORE_MISSING);
+                if (!$record) {
+                    return null;
+                }
+                if (!$this->assignment->can_view_submission($record->userid)) {
+                    return null;
+                }
+            }
+        } else {
+            // not supported for feedback plugins
+            return null;
+        }
+
+        $fs = get_file_storage();
+        $filepath = is_null($filepath) ? '/' : $filepath;
+        $filename = is_null($filename) ? '.' : $filename;
+        if (!($storedfile = $fs->get_file($this->assignment->get_context()->id,
+                                          $this->get_subtype() . '_' . $this->get_type(),
+                                          $filearea,
+                                          $itemid,
+                                          $filepath,
+                                          $filename))) {
+            return null;
+        }
+        return new file_info_stored($browser,
+                                    $this->assignment->get_context(),
+                                    $storedfile,
+                                    $urlbase,
+                                    $filearea,
+                                    $itemid,
+                                    true,
+                                    true,
+                                    false);
+    }
+
+}
diff --git a/mod/assign/backup/moodle2/backup_assign_activity_task.class.php b/mod/assign/backup/moodle2/backup_assign_activity_task.class.php
new file mode 100644 (file)
index 0000000..9f09426
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the backup activity for the assign module
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot . '/mod/assign/backup/moodle2/backup_assign_stepslib.php');
+//require_once($CFG->dirroot . '/mod/assign/backup/moodle2/backup_assign_settingslib.php');
+
+/**
+ * assign backup task that provides all the settings and steps to perform one complete backup of the activity
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class backup_assign_activity_task extends backup_activity_task {
+
+    /**
+     * Define (add) particular settings this activity can have
+     */
+    protected function define_my_settings() {
+        // No particular settings for this activity
+    }
+
+    /**
+     * Define (add) particular steps this activity can have
+     */
+    protected function define_my_steps() {
+        $this->add_step(new backup_assign_activity_structure_step('assign_structure', 'assign.xml'));
+    }
+
+    /**
+     * Code the transformations to perform in the activity in
+     * order to get transportable (encoded) links
+     * @param string $content
+     * @return string
+     */
+    static public function encode_content_links($content) {
+        global $CFG;
+
+        $base = preg_quote($CFG->wwwroot,"/");
+
+        // Link to the list of choices
+        $search="/(".$base."\/mod\/assign\/index.php\?id\=)([0-9]+)/";
+        $content= preg_replace($search, '$@ASSIGNINDEX*$2@$', $content);
+
+        // Link to choice view by moduleid
+        $search="/(".$base."\/mod\/assign\/view.php\?id\=)([0-9]+)/";
+        $content= preg_replace($search, '$@ASSIGNVIEWBYID*$2@$', $content);
+
+        return $content;
+    }
+
+}
+
diff --git a/mod/assign/backup/moodle2/backup_assign_stepslib.php b/mod/assign/backup/moodle2/backup_assign_stepslib.php
new file mode 100644 (file)
index 0000000..6ddee76
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Define all the backup steps that will be used by the backup_assign_activity_task
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Define the complete choice structure for backup, with file and id annotations
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class backup_assign_activity_structure_step extends backup_activity_structure_step {
+
+    /**
+     * Define the structure for the assign activity
+     * @return void
+     */
+    protected function define_structure() {
+
+        // To know if we are including userinfo
+        $userinfo = $this->get_setting_value('userinfo');
+
+        // Define each element separated
+        $assign = new backup_nested_element('assign', array('id'),
+                                            array('name',
+                                                  'intro',
+                                                  'introformat',
+                                                  'alwaysshowdescription',
+                                                  'preventlatesubmissions',
+                                                  'submissiondrafts',
+                                                  'sendnotifications',
+                                                  'duedate',
+                                                  'allowsubmissionsfromdate',
+                                                  'grade',
+                                                  'timemodified'));
+
+        $submissions = new backup_nested_element('submissions');
+
+        $submission = new backup_nested_element('submission', array('id'),
+                                                array('userid',
+                                                      'timecreated',
+                                                      'timemodified',
+                                                      'status'));
+
+        $grades = new backup_nested_element('grades');
+
+        $grade = new backup_nested_element('grade', array('id'),
+                                           array('userid',
+                                                 'timecreated',
+                                                 'timemodified',
+                                                 'grader',
+                                                 'grade',
+                                                 'locked',
+                                                 'mailed'));
+
+        $pluginconfigs = new backup_nested_element('plugin_configs');
+
+        $pluginconfig = new backup_nested_element('plugin_config', array('id'),
+                                                   array('plugin',
+                                                         'subtype',
+                                                         'name',
+                                                         'value'));
+
+        // Build the tree
+
+        $assign->add_child($submissions);
+        $submissions->add_child($submission);
+        $assign->add_child($grades);
+        $grades->add_child($grade);
+        $assign->add_child($pluginconfigs);
+        $pluginconfigs->add_child($pluginconfig);
+
+
+        // Define sources
+        $assign->set_source_table('assign', array('id' => backup::VAR_ACTIVITYID));
+
+        if ($userinfo) {
+            $submission->set_source_table('assign_submission',
+                                     array('assignment' => backup::VAR_PARENTID));
+
+            $grade->set_source_table('assign_grades',
+                                     array('assignment' => backup::VAR_PARENTID));
+            $pluginconfig->set_source_table('assign_plugin_config',
+                                     array('assignment' => backup::VAR_PARENTID));
+
+            // support 2 types of subplugins
+            $this->add_subplugin_structure('assignsubmission', $submission, true);
+            $this->add_subplugin_structure('assignfeedback', $grade, true);
+        }
+
+
+        // Define id annotations
+        $submission->annotate_ids('user', 'userid');
+        $grade->annotate_ids('user', 'userid');
+        $grade->annotate_ids('user', 'grader');
+
+        // Define file annotations
+        $assign->annotate_files('mod_assign', 'intro', null); // This file area hasn't itemid
+
+        // Return the root element (choice), wrapped into standard activity structure
+
+        return $this->prepare_activity_structure($assign);
+    }
+}
diff --git a/mod/assign/backup/moodle2/restore_assign_activity_task.class.php b/mod/assign/backup/moodle2/restore_assign_activity_task.class.php
new file mode 100644 (file)
index 0000000..900b1b8
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Define all the backup steps that will be used by the backup_assign_activity_task
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->dirroot . '/mod/assign/backup/moodle2/restore_assign_stepslib.php');
+
+/**
+ * assign restore task that provides all the settings and steps to perform one complete restore of the activity
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_assign_activity_task extends restore_activity_task {
+
+    /**
+     * Define (add) particular settings this activity can have
+     */
+    protected function define_my_settings() {
+        // No particular settings for this activity
+    }
+
+    /**
+     * Define (add) particular steps this activity can have
+     */
+    protected function define_my_steps() {
+        // Assign only has one structure step
+        $this->add_step(new restore_assign_activity_structure_step('assign_structure', 'assign.xml'));
+    }
+
+    /**
+     * Define the contents in the activity that must be
+     * processed by the link decoder
+     *
+     * @return array
+     */
+    static public function define_decode_contents() {
+        $contents = array();
+
+        $contents[] = new restore_decode_content('assign', array('intro'), 'assign');
+
+        return $contents;
+    }
+
+    /**
+     * Define the decoding rules for links belonging
+     * to the activity to be executed by the link decoder
+     *
+     * @return array of restore_decode_rule
+     */
+    static public function define_decode_rules() {
+        $rules = array();
+
+        $rules[] = new restore_decode_rule('ASSIGNVIEWBYID', '/mod/assign/view.php?id=$1', 'course_module');
+        $rules[] = new restore_decode_rule('ASSIGNINDEX', '/mod/assign/index.php?id=$1', 'course_module');
+
+        return $rules;
+
+    }
+
+    /**
+     * Define the restore log rules that will be applied
+     * by the {@link restore_logs_processor} when restoring
+     * assign logs. It must return one array
+     * of {@link restore_log_rule} objects
+     *
+     * @return array of restore_log_rule
+     */
+    static public function define_restore_log_rules() {
+        $rules = array();
+
+        $rules[] = new restore_log_rule('assign', 'add', 'view.php?id={course_module}', '{assign}');
+        $rules[] = new restore_log_rule('assign', 'update', 'view.php?id={course_module}', '{assign}');
+        $rules[] = new restore_log_rule('assign', 'view', 'view.php?id={course_module}', '{assign}');
+        // more...
+
+        return $rules;
+    }
+
+    /**
+     * Define the restore log rules that will be applied
+     * by the {@link restore_logs_processor} when restoring
+     * course logs. It must return one array
+     * of {@link restore_log_rule} objects
+     *
+     * Note this rules are applied when restoring course logs
+     * by the restore final task, but are defined here at
+     * activity level. All them are rules not linked to any module instance (cmid = 0)
+     *
+     * @return array
+     */
+    static public function define_restore_log_rules_for_course() {
+        $rules = array();
+
+        return $rules;
+    }
+
+}
diff --git a/mod/assign/backup/moodle2/restore_assign_stepslib.php b/mod/assign/backup/moodle2/restore_assign_stepslib.php
new file mode 100644 (file)
index 0000000..6ad6725
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Define all the restore steps that will be used by the restore_assign_activity_task
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Define the complete assignment structure for restore, with file and id annotations
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_assign_activity_structure_step extends restore_activity_structure_step {
+
+    /**
+     * Define the structure of the restore workflow
+     * @return restore_path_element $structure
+     */
+    protected function define_structure() {
+
+        $paths = array();
+        // To know if we are including userinfo
+        $userinfo = $this->get_setting_value('userinfo');
+
+        // Define each element separated
+        $paths[] = new restore_path_element('assign', '/activity/assign');
+        if ($userinfo) {
+            $submission = new restore_path_element('assign_submission', '/activity/assign/submissions/submission');
+            $paths[] = $submission;
+            $this->add_subplugin_structure('assignsubmission', $submission);
+            $grade = new restore_path_element('assign_grade', '/activity/assign/grades/grade');
+            $paths[] = $grade;
+            $this->add_subplugin_structure('assignfeedback', $grade);
+        }
+        $paths[] = new restore_path_element('assign_plugin_config', '/activity/assign/plugin_configs/plugin_config');
+
+        return $this->prepare_activity_structure($paths);
+    }
+
+    /**
+     * Process an assign restore
+     * @param object $data The data in object form
+     * @return void
+     */
+    protected function process_assign($data) {
+        global $DB;
+
+        $data = (object)$data;
+        $oldid = $data->id;
+        $data->course = $this->get_courseid();
+
+        $data->timemodified = $this->apply_date_offset($data->timemodified);
+        $data->allowsubmissionsfromdate = $this->apply_date_offset($data->allowsubmissionsfromdate);
+        $data->duedate = $this->apply_date_offset($data->duedate);
+
+
+        $newitemid = $DB->insert_record('assign', $data);
+
+        $this->apply_activity_instance($newitemid);
+    }
+
+    /**
+     * Process a submission restore
+     * @param object $data The data in object form
+     * @return void
+     */
+    protected function process_assign_submission($data) {
+        global $DB;
+
+        $data = (object)$data;
+        $oldid = $data->id;
+
+        $data->assignment = $this->get_new_parentid('assign');
+
+        $data->timemodified = $this->apply_date_offset($data->timemodified);
+        $data->timecreated = $this->apply_date_offset($data->timecreated);
+        $data->userid = $this->get_mappingid('user', $data->userid);
+
+        $newitemid = $DB->insert_record('assign_submission', $data);
+
+        // Note - the old contextid is required in order to be able to restore files stored in
+        // sub plugin file areas attached to the submissionid
+        $this->set_mapping('submission', $oldid, $newitemid, false, null, $this->task->get_old_contextid());
+    }
+
+    /**
+     * Process a grade restore
+     * @param object $data The data in object form
+     * @return void
+     */
+    protected function process_assign_grade($data) {
+        global $DB;
+
+        $data = (object)$data;
+        $oldid = $data->id;
+
+        $data->assignment = $this->get_new_parentid('assign');
+
+        $data->timemodified = $this->apply_date_offset($data->timemodified);
+        $data->timecreated = $this->apply_date_offset($data->timecreated);
+        $data->userid = $this->get_mappingid('user', $data->userid);
+        $data->grader = $this->get_mappingid('user', $data->grader);
+
+        $newitemid = $DB->insert_record('assign_grades', $data);
+
+        // Note - the old contextid is required in order to be able to restore files stored in
+        // sub plugin file areas attached to the gradeid
+        $this->set_mapping('grade', $oldid, $newitemid, false, null, $this->task->get_old_contextid());
+    }
+
+    /**
+     * Process a plugin-config restore
+     * @param object $data The data in object form
+     * @return void
+     */
+    protected function process_assign_plugin_config($data) {
+        global $DB;
+
+        $data = (object)$data;
+        $oldid = $data->id;
+
+        $data->assignment = $this->get_new_parentid('assign');
+
+        $newitemid = $DB->insert_record('assign_plugin_config', $data);
+
+    }
+
+    /**
+     * Once the database tables have been fully restored, restore the files
+     * @return void
+     */
+    protected function after_execute() {
+        $this->add_related_files('mod_assign', 'intro', null);
+    }
+}
diff --git a/mod/assign/db/access.php b/mod/assign/db/access.php
new file mode 100644 (file)
index 0000000..9f8cde7
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Capability definitions for this module.
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$capabilities = array(
+
+    'mod/assign:view' => array(
+
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_MODULE,
+        'archetypes' => array(
+            'guest' => CAP_ALLOW,
+            'student' => CAP_ALLOW,
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        )
+    ),
+
+    'mod/assign:submit' => array(
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_MODULE,
+        'archetypes' => array(
+            'student' => CAP_ALLOW
+        )
+    ),
+
+    'mod/assign:grade' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_MODULE,
+        'archetypes' => array(
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        )
+    ),
+
+    'mod/assign:exportownsubmission' => array(
+
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_MODULE,
+        'archetypes' => array(
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW,
+            'student' => CAP_ALLOW,
+        )
+    ),
+
+    'mod/assign:addinstance' => array(
+        'riskbitmask' => RISK_XSS,
+
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'archetypes' => array(
+            'editingteacher' => CAP_ALLOW,
+            'manager' => CAP_ALLOW
+        ),
+        'clonepermissionsfrom' => 'moodle/course:manageactivities'
+    ),
+);
+
+
diff --git a/mod/assign/db/events.php b/mod/assign/db/events.php
new file mode 100644 (file)
index 0000000..24446f8
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * List of events generated by the assignment module
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$handlers = array();
+
+/* List of events thrown from assignment module
+
+assignment_finalize_sent - object course, object user, object cm, object assignment, fileareaname
+assignment_file_sent     - object course, object user, object cm, object assignment, object file
+
+*/
diff --git a/mod/assign/db/install.xml b/mod/assign/db/install.xml
new file mode 100644 (file)
index 0000000..273486b
--- /dev/null
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="mod/assign/db" VERSION="20120423" COMMENT="XMLDB file for Moodle mod/assign"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
+>
+  <TABLES>
+    <TABLE NAME="assign" COMMENT="This table saves information about an instance of mod_assign in a course." NEXT="assign_submission">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="course"/>
+        <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
+        <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the instance of the assignment. Displayed at the top of each page." PREVIOUS="course" NEXT="intro"/>
+        <FIELD NAME="intro" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="The description of the assignment. This field is used by feature MOD_INTRO." PREVIOUS="name" NEXT="introformat"/>
+        <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the description field of the assignment. This field is used by feature MOD_INTRO." PREVIOUS="intro" NEXT="alwaysshowdescription"/>
+        <FIELD NAME="alwaysshowdescription" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If false the assignment intro will only be displayed after the allowsubmissionsfrom date. If true it will always be displayed." PREVIOUS="introformat" NEXT="nosubmissions"/>
+        <FIELD NAME="nosubmissions" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="This field is a cache for is_any_submission_plugin_enabled() which allows Moodle pages to distinguish offline assignment types without loading the assignment class." PREVIOUS="alwaysshowdescription" NEXT="preventlatesubmissions"/>
+        <FIELD NAME="preventlatesubmissions" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If true, submissions will not be accepted past the due date." PREVIOUS="nosubmissions" NEXT="submissiondrafts"/>
+        <FIELD NAME="submissiondrafts" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If true, assignment submissions will be considered drafts until the student clicks on the submit assignmnet button." PREVIOUS="preventlatesubmissions" NEXT="sendnotifications"/>
+        <FIELD NAME="sendnotifications" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Allows the disabling of email notifications in the assign module." PREVIOUS="submissiondrafts" NEXT="duedate"/>
+        <FIELD NAME="duedate" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The due date for the assignment. Displayed to students." PREVIOUS="sendnotifications" NEXT="allowsubmissionsfromdate"/>
+        <FIELD NAME="allowsubmissionsfromdate" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="If set, submissions will only be accepted after this date." PREVIOUS="duedate" NEXT="grade"/>
+        <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The maximum grade for this assignment. Can be negative to indicate the use of a scale." PREVIOUS="allowsubmissionsfromdate" NEXT="timemodified"/>
+        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The time the settings for this assign module instance were last modified." PREVIOUS="grade"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this assignment instance."/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="course" UNIQUE="false" FIELDS="course" COMMENT="The course this assignment instance belongs to."/>
+      </INDEXES>
+    </TABLE>
+    <TABLE NAME="assign_submission" COMMENT="This table keeps information about student interactions with the mod/assign. This is limited to metadata about a student submission but does not include the submission itself which is stored by plugins." PREVIOUS="assign" NEXT="assign_grades">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="assignment"/>
+        <FIELD NAME="assignment" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="userid"/>
+        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="assignment" NEXT="timecreated"/>
+        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The time of the first student submission to this assignment." PREVIOUS="userid" NEXT="timemodified"/>
+        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The last time this assignment submission was modified by a student." PREVIOUS="timecreated" NEXT="status"/>
+        <FIELD NAME="status" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="The status of this assignment submission. The current statuses are DRAFT and SUBMITTED." PREVIOUS="timemodified"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this assignment submission." NEXT="assignment"/>
+        <KEY NAME="assignment" TYPE="foreign" FIELDS="assignment" REFTABLE="assign" REFFIELDS="id" COMMENT="The instance of mod_assign this submission belongs to." PREVIOUS="primary"/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="userid" UNIQUE="false" FIELDS="userid"/>
+      </INDEXES>
+    </TABLE>
+    <TABLE NAME="assign_grades" COMMENT="Grading information about a single assignment submission." PREVIOUS="assign_submission" NEXT="assign_plugin_config">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="assignment"/>
+        <FIELD NAME="assignment" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="userid"/>
+        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="assignment" NEXT="timecreated"/>
+        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The time the assignment submission was first modified by a grader." PREVIOUS="userid" NEXT="timemodified"/>
+        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The most recent modification time for the assignment submission by a grader." PREVIOUS="timecreated" NEXT="grader"/>
+        <FIELD NAME="grader" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timemodified" NEXT="grade"/>
+        <FIELD NAME="grade" TYPE="number" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false" DECIMALS="5" COMMENT="The numerical grade for this assignment submission. Can be determined by scales/advancedgradingforms etc but will always be converted back to a floating point number." PREVIOUS="grader" NEXT="locked"/>
+        <FIELD NAME="locked" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="A flag to prevent changes for a single student submission." PREVIOUS="grade" NEXT="mailed"/>
+        <FIELD NAME="mailed" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="locked"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this grade." NEXT="assignment"/>
+        <KEY NAME="assignment" TYPE="foreign" FIELDS="assignment" REFTABLE="assign" REFFIELDS="id" COMMENT="The assignment instance this grade belongs to." PREVIOUS="primary"/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="userid" UNIQUE="false" FIELDS="userid" COMMENT="The userid for the submission relating to this grade." NEXT="mailed"/>
+        <INDEX NAME="mailed" UNIQUE="false" FIELDS="mailed" COMMENT="True if notifications have been sent about the most recent grader update about this submission." PREVIOUS="userid"/>
+      </INDEXES>
+    </TABLE>
+    <TABLE NAME="assign_plugin_config" COMMENT="Config data for an instance of a plugin in an assignment." PREVIOUS="assign_grades">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="assignment"/>
+        <FIELD NAME="assignment" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="plugin"/>
+        <FIELD NAME="plugin" TYPE="char" LENGTH="28" NOTNULL="true" SEQUENCE="false" PREVIOUS="assignment" NEXT="subtype"/>
+        <FIELD NAME="subtype" TYPE="char" LENGTH="28" NOTNULL="true" SEQUENCE="false" PREVIOUS="plugin" NEXT="name"/>
+        <FIELD NAME="name" TYPE="char" LENGTH="28" NOTNULL="true" SEQUENCE="false" PREVIOUS="subtype" NEXT="value"/>
+        <FIELD NAME="value" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The value of the config setting. Stored as text but can be interpreted by the plugin however it likes." PREVIOUS="name"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Unique id to identify this plugin setting value." NEXT="assignment"/>
+        <KEY NAME="assignment" TYPE="foreign" FIELDS="assignment" REFTABLE="assign" REFFIELDS="id" COMMENT="The assignment instance this config value relates to." PREVIOUS="primary"/>
+      </KEYS>
+      <INDEXES>
+        <INDEX NAME="plugin" UNIQUE="false" FIELDS="plugin" COMMENT="The type of this plugin." NEXT="subtype"/>
+        <INDEX NAME="subtype" UNIQUE="false" FIELDS="subtype" COMMENT="The subtype of this plugin (assign_submission or assign_feedback)." PREVIOUS="plugin" NEXT="name"/>
+        <INDEX NAME="name" UNIQUE="false" FIELDS="name" COMMENT="The name of this plugin setting." PREVIOUS="subtype"/>
+      </INDEXES>
+    </TABLE>
+  </TABLES>
+</XMLDB>
diff --git a/mod/assign/db/log.php b/mod/assign/db/log.php
new file mode 100644 (file)
index 0000000..fc4c39e
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Definition of log events
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+$logs = array(
+    array('module'=>'assign', 'action'=>'view', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'add', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'update', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'view submission', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'view feedback', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'upload', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'download all submissions', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'view grading form', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'delete mod', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'view submission grading table', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'view submit assignment form', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'submit for grading', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'submit', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'revert submission to draft', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'lock submission', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'unlock submission', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'grade submission', 'mtable'=>'assign', 'field'=>'name'),
+    array('module'=>'assign', 'action'=>'view all', 'mtable'=>'course', 'field'=>'fullname'),
+);
diff --git a/mod/assign/db/messages.php b/mod/assign/db/messages.php
new file mode 100644 (file)
index 0000000..1df087f
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Defines message providers (types of messages being sent)
+ *
+ * @package mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$messageproviders = array (
+
+// Ordinary assignment submissions
+    'assign_updates' => array (
+    )
+
+);
diff --git a/mod/assign/db/subplugins.php b/mod/assign/db/subplugins.php
new file mode 100644 (file)
index 0000000..be0d707
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Definition of sub-plugins
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$subplugins = array('assignsubmission'=>'mod/assign/submission', 'assignfeedback'=>'mod/assign/feedback');
diff --git a/mod/assign/db/upgrade.php b/mod/assign/db/upgrade.php
new file mode 100644 (file)
index 0000000..03ee8f4
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Upgrade code for install
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * upgrade this assignment instance - this function could be skipped but it will be needed later
+ * @param int $oldversion The old version of the assign module
+ * @return bool
+ */
+function xmldb_assign_upgrade($oldversion) {
+    return true;
+}
+
+
diff --git a/mod/assign/feedback/comments/backup/moodle2/backup_assignfeedback_comments_subplugin.class.php b/mod/assign/feedback/comments/backup/moodle2/backup_assignfeedback_comments_subplugin.class.php
new file mode 100644 (file)
index 0000000..3faff44
--- /dev/null
@@ -0,0 +1,58 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the class for backup of this feedback plugin
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Provides the information to backup comments feedback
+ *
+ * This just records the text and format
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class backup_assignfeedback_comments_subplugin extends backup_subplugin {
+
+    /**
+     * Returns the subplugin information to attach to submission element
+     * @return backup_subplugin_element
+     */
+    protected function define_grade_subplugin_structure() {
+
+        // create XML elements
+        $subplugin = $this->get_subplugin_element(); // virtual optigroup element
+        $subpluginwrapper = new backup_nested_element($this->get_recommended_name());
+        $subpluginelement = new backup_nested_element('feedback_comments', null, array('commenttext', 'commentformat', 'grade'));
+
+        // connect XML elements into the tree
+        $subplugin->add_child($subpluginwrapper);
+        $subpluginwrapper->add_child($subpluginelement);
+
+        // set source to populate the data
+        $subpluginelement->set_source_table('assignfeedback_comments', array('grade' => backup::VAR_PARENTID));
+
+        return $subplugin;
+    }
+}
diff --git a/mod/assign/feedback/comments/backup/moodle2/restore_assignfeedback_comments_subplugin.class.php b/mod/assign/feedback/comments/backup/moodle2/restore_assignfeedback_comments_subplugin.class.php
new file mode 100644 (file)
index 0000000..7e38515
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * restore subplugin class that provides the necessary information needed to restore one assign_submission subplugin.
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * restore subplugin class that provides the necessary information needed to restore one assignfeedback subplugin.
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_assignfeedback_comments_subplugin extends restore_subplugin {
+
+    /**
+     * Returns the paths to be handled by the subplugin at workshop level
+     * @return array
+     */
+    protected function define_grade_subplugin_structure() {
+
+        $paths = array();
+
+        $elename = $this->get_namefor('grade');
+        $elepath = $this->get_pathfor('/feedback_comments'); // we used get_recommended_name() so this works
+        $paths[] = new restore_path_element($elename, $elepath);
+
+        return $paths; // And we return the interesting paths
+    }
+
+    /**
+     * Processes one feedback_comments element
+     * @param mixed $data
+     */
+    public function process_assignfeedback_comments_grade($data) {
+        global $DB;
+
+        $data = (object)$data;
+        $data->assignment = $this->get_new_parentid('assign');
+        $oldgradeid = $data->grade;
+        // the mapping is set in the restore for the core assign activity. When a grade node is processed
+        $data->grade = $this->get_mappingid('grade', $data->grade);
+
+        $DB->insert_record('assignfeedback_comments', $data);
+    }
+}
diff --git a/mod/assign/feedback/comments/db/access.php b/mod/assign/feedback/comments/db/access.php
new file mode 100644 (file)
index 0000000..6d5457f
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Capability definitions for this module.
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$capabilities = array(
+
+);
\ No newline at end of file
diff --git a/mod/assign/feedback/comments/db/install.php b/mod/assign/feedback/comments/db/install.php
new file mode 100644 (file)
index 0000000..f8c093b
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Post-install code for the feedback_comments module.
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Set the initial order for the feedback comments plugin (top)
+ * @return bool
+ */
+function xmldb_assignfeedback_comments_install() {
+    global $CFG;
+
+    // do the install
+    require_once($CFG->dirroot . '/mod/assign/adminlib.php');
+
+    // set the correct initial order for the plugins
+    $pluginmanager = new assign_plugin_manager('assignfeedback');
+    $pluginmanager->move_plugin('comments', 'up');
+
+    // do the upgrades
+    return true;
+}
diff --git a/mod/assign/feedback/comments/db/install.xml b/mod/assign/feedback/comments/db/install.xml
new file mode 100644 (file)
index 0000000..3096e18
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="mod/assign/feedback/comments/db" VERSION="20120423" COMMENT="XMLDB file for Moodle mod/assign/feedback/comments"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="../../../../../lib/xmldb/xmldb.xsd"
+>
+  <TABLES>
+    <TABLE NAME="assignfeedback_comments" COMMENT="Text feedback for submitted assignments">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="assignment"/>
+        <FIELD NAME="assignment" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="grade"/>
+        <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="assignment" NEXT="commenttext"/>
+        <FIELD NAME="commenttext" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The feedback text" PREVIOUS="grade" NEXT="commentformat"/>
+        <FIELD NAME="commentformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The feedback text format" PREVIOUS="commenttext"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="The unique id for this feedback" NEXT="assignment"/>
+        <KEY NAME="assignment" TYPE="foreign" FIELDS="assignment" REFTABLE="assign" REFFIELDS="id" COMMENT="The assignment instance this feedback relates to." PREVIOUS="primary" NEXT="grade"/>
+        <KEY NAME="grade" TYPE="foreign" FIELDS="grade" REFTABLE="assign_grade" REFFIELDS="id" COMMENT="The grade instance this feedback relates to." PREVIOUS="assignment"/>
+      </KEYS>
+    </TABLE>
+  </TABLES>
+</XMLDB>
diff --git a/mod/assign/feedback/comments/db/upgrade.php b/mod/assign/feedback/comments/db/upgrade.php
new file mode 100644 (file)
index 0000000..b46002d
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Upgrade code for the feedback_comments module.
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Stub for upgrade code
+ * @param int $oldversion
+ * @return bool
+ */
+function xmldb_feedback_comments_upgrade($oldversion) {
+    // do the upgrades
+    return true;
+}
+
+
diff --git a/mod/assign/feedback/comments/lang/en/assignfeedback_comments.php b/mod/assign/feedback/comments/lang/en/assignfeedback_comments.php
new file mode 100644 (file)
index 0000000..2eeab17
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Strings for component 'assignfeedback_comments', language 'en'
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+$string['pluginname'] = 'Feedback comments';
+$string['enabled'] = 'Feedback comments';
+$string['enabled_help'] = 'If enabled, the marker can leave feedback comments for each submission. ';
+
diff --git a/mod/assign/feedback/comments/locallib.php b/mod/assign/feedback/comments/locallib.php
new file mode 100644 (file)
index 0000000..e68764a
--- /dev/null
@@ -0,0 +1,248 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the definition for the library class for comment feedback plugin
+ *
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+ defined('MOODLE_INTERNAL') || die();
+
+/**
+ * library class for comment feedback plugin extending feedback plugin base class
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class assign_feedback_comments extends assign_feedback_plugin {
+
+   /**
+    * Get the name of the online comment feedback plugin
+    * @return string
+    */
+    public function get_name() {
+        return get_string('pluginname', 'assignfeedback_comments');
+    }
+
+    /**
+     * Get the feedback comment from the database
+     *
+     * @param int $gradeid
+     * @return stdClass|false The feedback comments for the given grade if it exists. False if it doesn't.
+     */
+    public function get_feedback_comments($gradeid) {
+        global $DB;
+        return $DB->get_record('assignfeedback_comments', array('grade'=>$gradeid));
+    }
+
+    /**
+     * Get form elements for the grading page
+     *
+     * @param stdClass|null $grade
+     * @param MoodleQuickForm $mform
+     * @param stdClass $data
+     * @return bool true if elements were added to the form
+     */
+    public function get_form_elements($grade, MoodleQuickForm $mform, stdClass $data) {
+        if ($grade) {
+            $feedbackcomments = $this->get_feedback_comments($grade->id);
+            if ($feedbackcomments) {
+                $data->feedbackcomments_editor['text'] = $feedbackcomments->commenttext;
+                $data->feedbackcomments_editor['format'] = $feedbackcomments->commentformat;
+            }
+        }
+
+        $mform->addElement('editor', 'assignfeedbackcomments_editor', '', null, null);
+        return true;
+    }
+
+    /**
+     * Saving the comment content into dtabase
+     *
+     * @param stdClass $grade
+     * @param stdClass $data
+     * @return bool
+     */
+    public function save(stdClass $grade, stdClass $data) {
+        global $DB;
+        $feedbackcomment = $this->get_feedback_comments($grade->id);
+        if ($feedbackcomment) {
+            $feedbackcomment->commenttext = $data->assignfeedbackcomments_editor['text'];
+            $feedbackcomment->commentformat = $data->assignfeedbackcomments_editor['format'];
+            return $DB->update_record('assignfeedback_comments', $feedbackcomment);
+        } else {
+            $feedbackcomment = new stdClass();
+            $feedbackcomment->commenttext = $data->assignfeedbackcomments_editor['text'];
+            $feedbackcomment->commentformat = $data->assignfeedbackcomments_editor['format'];
+            $feedbackcomment->grade = $grade->id;
+            $feedbackcomment->assignment = $this->assignment->get_instance()->id;
+            return $DB->insert_record('assignfeedback_comments', $feedbackcomment) > 0;
+        }
+    }
+
+    /**
+     * display the comment in the feedback table
+     *
+     * @param stdClass $grade
+     * @param bool $showviewlink Set to true to show a link to view the full feedback
+     * @return string
+     */
+    public function view_summary(stdClass $grade, $showviewlink) {
+        $feedbackcomments = $this->get_feedback_comments($grade->id);
+        if ($feedbackcomments) {
+            $text = format_text($feedbackcomments->commenttext, $feedbackcomments->commentformat, array('context' => $this->assignment->get_context()));
+            $short = shorten_text($text, 140);
+
+            // show the view all link if the text has been shortened
+            $showviewlink = $short != $text;
+            return $short;
+        }
+        return '';
+    }
+
+    /**
+     * display the comment in the feedback table
+     *
+     * @param stdClass $grade
+     * @return string
+     */
+    public function view(stdClass $grade) {
+        $feedbackcomments = $this->get_feedback_comments($grade->id);
+        if ($feedbackcomments) {
+            return format_text($feedbackcomments->commenttext, $feedbackcomments->commentformat, array('context' => $this->assignment->get_context()));
+        }
+        return '';
+    }
+  
+    /**
+     * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
+     * and version.
+     *
+     * @param string $type old assignment subtype
+     * @param int $version old assignment version
+     * @return bool True if upgrade is possible
+     */
+    public function can_upgrade($type, $version) {
+
+        if (($type == 'upload' || $type == 'uploadsingle') && $version >= 2011112900) {
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Upgrade the settings from the old assignment to the new plugin based one
+     *
+     * @param context $oldcontext - the context for the old assignment
+     * @param stdClass $oldassignment - the data for the old assignment
+     * @param string $log - can be appended to by the upgrade
+     * @return bool was it a success? (false will trigger a rollback)
+     */
+    public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
+        // first upgrade settings (nothing to do)
+        return true;
+    }
+
+    /**
+     * Upgrade the feedback from the old assignment to the new one
+     *
+     * @param context $oldcontext - the database for the old assignment context
+     * @param stdClass $oldassignment The data record for the old assignment
+     * @param stdClass $oldsubmission The data record for the old submission
+     * @param stdClass $grade The data record for the new grade
+     * @param string $log Record upgrade messages in the log
+     * @return bool true or false - false will trigger a rollback
+     */
+    public function upgrade(context $oldcontext, stdClass $oldassignment, stdClass $oldsubmission, stdClass $grade, & $log) {
+        global $DB;
+
+        $feedbackcomments = new stdClass();
+        $feedbackcomments->commenttext = $oldsubmission->submissioncomment;
+        $feedbackcomments->commentformat = FORMAT_HTML;
+
+        $feedbackcomments->grade = $grade->id;
+        $feedbackcomments->assignment = $this->assignment->get_instance()->id;
+        if (!$DB->insert_record('assignfeedback_comments', $feedbackcomments) > 0) {
+            $log .= get_string('couldnotconvertgrade', 'mod_assign', $grade->userid);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * If this plugin adds to the gradebook comments field, it must specify the format of the text
+     * of the comment
+     *
+     * Only one feedback plugin can push comments to the gradebook and that is chosen by the assignment
+     * settings page.
+     *
+     * @param stdClass $grade The grade
+     * @return int
+     */
+    public function format_for_gradebook(stdClass $grade) {
+        $feedbackcomments = $this->get_feedback_comments($grade->id);
+        if ($feedbackcomments) {
+            return $feedbackcomments->commentformat;
+        }
+        return FORMAT_MOODLE;
+    }
+
+    /**
+     * If this plugin adds to the gradebook comments field, it must format the text
+     * of the comment
+     *
+     * Only one feedback plugin can push comments to the gradebook and that is chosen by the assignment
+     * settings page.
+     *
+     * @param stdClass $grade The grade
+     * @return string
+     */
+    public function text_for_gradebook(stdClass $grade) {
+        $feedbackcomments = $this->get_feedback_comments($grade->id);
+        if ($feedbackcomments) {
+            return $feedbackcomments->commenttext;
+        }
+        return '';
+    }
+
+    /**
+     * The assignment has been deleted - cleanup
+     *
+     * @return bool
+     */
+    public function delete_instance() {
+        global $DB;
+        // will throw exception on failure
+        $DB->delete_records('assignfeedback_comments', array('assignment'=>$this->assignment->get_instance()->id));
+        return true;
+    }
+
+    /**
+     * Returns true if there are no feedback comments for the given grade
+     *
+     * @param stdClass $grade
+     * @return bool
+     */
+    public function is_empty(stdClass $grade) {
+        return $this->view($grade) == '';
+    }
+}
diff --git a/mod/assign/feedback/comments/version.php b/mod/assign/feedback/comments/version.php
new file mode 100644 (file)
index 0000000..720ae40
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the version information for the comments feedback plugin
+ *
+ * @package   assignfeedback_comments
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$plugin->version   = 2012011600;
+$plugin->requires  = 2011110200;
+$plugin->component = 'assignfeedback_comments';
diff --git a/mod/assign/feedback/file/backup/moodle2/backup_assignfeedback_file_subplugin.class.php b/mod/assign/feedback/file/backup/moodle2/backup_assignfeedback_file_subplugin.class.php
new file mode 100644 (file)
index 0000000..497a7c1
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the backup code for the feedback_file plugin.
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Provides the information to backup feedback files
+ *
+ * This just adds its filearea to the annotations and records the number of files
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class backup_assignfeedback_file_subplugin extends backup_subplugin {
+
+    /**
+     * Returns the subplugin information to attach to feedback element
+     * @return backup_subplugin_element
+     */
+    protected function define_grade_subplugin_structure() {
+
+        // create XML elements
+        $subplugin = $this->get_subplugin_element(); // virtual optigroup element
+        $subpluginwrapper = new backup_nested_element($this->get_recommended_name());
+        $subpluginelement = new backup_nested_element('feedback_file', null, array('numfiles', 'grade'));
+
+        // connect XML elements into the tree
+        $subplugin->add_child($subpluginwrapper);
+        $subpluginwrapper->add_child($subpluginelement);
+
+        // set source to populate the data
+        $subpluginelement->set_source_table('assignfeedback_file', array('grade' => backup::VAR_PARENTID));
+
+        $subpluginelement->annotate_files('assignfeedback_file', 'feedback_files', 'grade');// The parent is the grade
+        return $subplugin;
+    }
+
+}
diff --git a/mod/assign/feedback/file/backup/moodle2/restore_assignfeedback_file_subplugin.class.php b/mod/assign/feedback/file/backup/moodle2/restore_assignfeedback_file_subplugin.class.php
new file mode 100644 (file)
index 0000000..3ce98ed
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the restore code for the feedback_file plugin.
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * restore subplugin class that provides the necessary information needed to restore one assign_feedback subplugin.
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class restore_assignfeedback_file_subplugin extends restore_subplugin {
+
+    /**
+     * Returns the paths to be handled by the subplugin at assignment level
+     * @return array
+     */
+    protected function define_grade_subplugin_structure() {
+
+        $paths = array();
+
+        $elename = $this->get_namefor('grade');
+        $elepath = $this->get_pathfor('/feedback_file'); // we used get_recommended_name() so this works
+        $paths[] = new restore_path_element($elename, $elepath);
+
+        return $paths; // And we return the interesting paths
+    }
+
+    /**
+     * Processes one feedback_file element
+     * @param mixed $data
+     */
+    public function process_assignfeedback_file_grade($data) {
+        global $DB;
+
+        $data = (object)$data;
+        $data->assignment = $this->get_new_parentid('assign');
+        $oldgradeid = $data->grade;
+        // the mapping is set in the restore for the core assign activity. When a grade node is processed
+        $data->grade = $this->get_mappingid('grade', $data->grade);
+
+        $DB->insert_record('assignfeedback_file', $data);
+
+        $this->add_related_files('assignfeedback_file', 'feedback_files', 'grade', null, $oldgradeid);
+    }
+
+}
diff --git a/mod/assign/feedback/file/db/access.php b/mod/assign/feedback/file/db/access.php
new file mode 100644 (file)
index 0000000..05e28bd
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Capability definitions for this module.
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+$capabilities = array();
+
+
diff --git a/mod/assign/feedback/file/db/install.php b/mod/assign/feedback/file/db/install.php
new file mode 100644 (file)
index 0000000..65c302f
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Post-install code for the assignfeedback_file module.
+ *
+ * @package assignfeedback_file
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+
+/**
+ * Code run after the assignfeedback_file module database tables have been created.
+ * Moves the feedback file plugin down
+ *
+ * @return bool
+ */
+function xmldb_assignfeedback_file_install() {
+    global $CFG;
+
+    // do the install
+
+    require_once($CFG->dirroot . '/mod/assign/adminlib.php');
+    // set the correct initial order for the plugins
+    $pluginmanager = new assign_plugin_manager('assignfeedback');
+
+    $pluginmanager->move_plugin('file', 'down');
+
+    // do the upgrades
+    return true;
+}
+
+
diff --git a/mod/assign/feedback/file/db/install.xml b/mod/assign/feedback/file/db/install.xml
new file mode 100644 (file)
index 0000000..7aa96c5
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="mod/assign/feedback/file/db" VERSION="20120423" COMMENT="XMLDB file for Moodle mod/assign/feedback/file"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="../../../../../lib/xmldb/xmldb.xsd"
+>
+  <TABLES>
+    <TABLE NAME="assignfeedback_file" COMMENT="Stores info about the number of files submitted by a student.">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="assignment"/>
+        <FIELD NAME="assignment" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="grade"/>
+        <FIELD NAME="grade" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="assignment" NEXT="numfiles"/>
+        <FIELD NAME="numfiles" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The number of files uploaded by a grader." PREVIOUS="grade"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Unique id for this feedback value." NEXT="assignment"/>
+        <KEY NAME="assignment" TYPE="foreign" FIELDS="assignment" REFTABLE="assign" REFFIELDS="id" COMMENT="The assignment instance this feedback relates to." PREVIOUS="primary" NEXT="grade"/>
+        <KEY NAME="grade" TYPE="foreign" FIELDS="grade" REFTABLE="assign_grade" REFFIELDS="id" COMMENT="The grade instance this feedback relates to." PREVIOUS="assignment"/>
+      </KEYS>
+    </TABLE>
+  </TABLES>
+</XMLDB>
diff --git a/mod/assign/feedback/file/db/upgrade.php b/mod/assign/feedback/file/db/upgrade.php
new file mode 100644 (file)
index 0000000..22ae296
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Upgrade code for the feedback_file module.
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Stub for upgrade code
+ * @param int $oldversion
+ * @return bool
+ */
+function xmldb_feedback_file_upgrade($oldversion) {
+    // do the upgrades
+    return true;
+}
+
+
diff --git a/mod/assign/feedback/file/lang/en/assignfeedback_file.php b/mod/assign/feedback/file/lang/en/assignfeedback_file.php
new file mode 100644 (file)
index 0000000..0ba7719
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Strings for component 'feedback_file', language 'en'
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['configmaxbytes'] = 'Maximum file size';
+$string['enabled'] = 'File feedback';
+$string['enabled_help'] = 'If enabled, the teacher will be able to upload files with feedback when marking the assignments. These files may be, but are not limited to marked up student submissions, documents with comments or spoken audio feedback. ';
+$string['file'] = 'Feedback files';
+$string['maxbytes'] = 'Maximum file size';
+$string['maxfiles'] = 'Maximum number of uploaded files';
+$string['maximumsize'] = 'Maximum file size';
+$string['pluginname'] = 'File feedback';
diff --git a/mod/assign/feedback/file/lib.php b/mod/assign/feedback/file/lib.php
new file mode 100644 (file)
index 0000000..87ba684
--- /dev/null
@@ -0,0 +1,73 @@
+<?PHP
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the moodle hooks for the feedback file plugin
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Serves assignment feedback and other files.
+ *
+ * @param mixed $course course or id of the course
+ * @param mixed $cm course module or id of the course module
+ * @param context $context
+ * @param string $filearea
+ * @param array $args
+ * @param bool $forcedownload
+ * @return bool false if file not found, does not return if found - just send the file
+ */
+function assignfeedback_file_pluginfile($course, $cm, context $context, $filearea, $args, $forcedownload) {
+    global $USER, $DB;
+
+    if ($context->contextlevel != CONTEXT_MODULE) {
+        return false;
+    }
+
+    require_login($course, false, $cm);
+    $itemid = (int)array_shift($args);
+    $record = $DB->get_record('assign_grades', array('id'=>$itemid), 'userid,assignment', MUST_EXIST);
+    $userid = $record->userid;
+
+
+    if (!$assign = $DB->get_record('assign', array('id'=>$cm->instance))) {
+        return false;
+    }
+
+    if ($assign->id != $record->assignment) {
+        return false;
+    }
+
+
+    // check is users feedback or has grading permission
+    if ($USER->id != $userid and !has_capability('mod/assign:grade', $context)) {
+        return false;
+    }
+
+    $relativepath = implode('/', $args);
+
+    $fullpath = "/{$context->id}/assignfeedback_file/$filearea/$itemid/$relativepath";
+
+    $fs = get_file_storage();
+    if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+        return false;
+    }
+    send_stored_file($file, 0, 0, true); // download MUST be forced - security!
+}
diff --git a/mod/assign/feedback/file/locallib.php b/mod/assign/feedback/file/locallib.php
new file mode 100644 (file)
index 0000000..21c0223
--- /dev/null
@@ -0,0 +1,264 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the definition for the library class for file feedback plugin
+ *
+ *
+ * @package   assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+/**
+ * File areas for file feedback assignment
+ */
+define('ASSIGN_MAX_FEEDBACK_FILES', 20);
+define('ASSIGN_FILEAREA_FEEDBACK_FILES', 'feedback_files');
+define('ASSIGN_FEEDBACK_FILE_MAX_SUMMARY_FILES', 5);
+
+/**
+ * library class for file feedback plugin extending feedback plugin base class
+ *
+ * @package   asignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class assign_feedback_file extends assign_feedback_plugin {
+
+    /**
+     * Get the name of the file feedback plugin
+     * @return string
+     */
+    public function get_name() {
+        return get_string('file', 'assignfeedback_file');
+    }
+
+    /**
+     * Get file feedback information from the database
+     *
+     * @param int $gradeid
+     * @return mixed
+     */
+    public function get_file_feedback($gradeid) {
+        global $DB;
+        return $DB->get_record('assignfeedback_file', array('grade'=>$gradeid));
+    }
+
+    /**
+     * File format options
+     * @return array
+     */
+    private function get_file_options() {
+        global $COURSE;
+
+        $fileoptions = array('subdirs'=>1,
+                                'maxbytes'=>$COURSE->maxbytes,
+                                'accepted_types'=>'*',
+                                'return_types'=>FILE_INTERNAL);
+        return $fileoptions;
+    }
+
+    /**
+     * Get form elements for grading form
+     *
+     * @param stdClass $grade 
+     * @param MoodleQuickForm $mform
+     * @param stdClass $data
+     * @return bool true if elements were added to the form
+     */
+    public function get_form_elements($grade, MoodleQuickForm $mform, stdClass $data) {
+
+        $fileoptions = $this->get_file_options();
+        $gradeid = $grade ? $grade->id : 0;
+
+
+        $data = file_prepare_standard_filemanager($data, 'files', $fileoptions, $this->assignment->get_context(), 'assignfeedback_file', ASSIGN_FILEAREA_FEEDBACK_FILES, $gradeid);
+
+        $mform->addElement('filemanager', 'files_filemanager', '', null, $fileoptions);
+
+        return true;
+    }
+
+    /**
+     * Count the number of files
+     *
+     * @param int $gradeid
+     * @param string $area
+     * @return int
+     */
+    private function count_files($gradeid, $area) {
+        global $USER;
+
+        $fs = get_file_storage();
+        $files = $fs->get_area_files($this->assignment->get_context()->id, 'assignfeedback_file', $area, $gradeid, "id", false);
+
+        return count($files);
+    }
+
+    /**
+     * Save the feedback files
+     *
+     * @param stdClass $grade
+     * @param stdClass $data
+     * @return bool
+     */
+    public function save(stdClass $grade, stdClass $data) {
+
+        global $DB;
+
+        $fileoptions = $this->get_file_options();
+
+
+        $data = file_postupdate_standard_filemanager($data, 'files', $fileoptions, $this->assignment->get_context(), 'assignfeedback_file', ASSIGN_FILEAREA_FEEDBACK_FILES, $grade->id);
+
+
+        $filefeedback = $this->get_file_feedback($grade->id);
+        if ($filefeedback) {
+            $filefeedback->numfiles = $this->count_files($grade->id, ASSIGN_FILEAREA_FEEDBACK_FILES);
+            return $DB->update_record('assignfeedback_file', $filefeedback);
+        } else {
+            $filefeedback = new stdClass();
+            $filefeedback->numfiles = $this->count_files($grade->id, ASSIGN_FILEAREA_FEEDBACK_FILES);
+            $filefeedback->grade = $grade->id;
+            $filefeedback->assignment = $this->assignment->get_instance()->id;
+            return $DB->insert_record('assignfeedback_file', $filefeedback) > 0;
+        }
+    }
+
+    /**
+     * Display the list of files  in the feedback status table
+     *
+     * @param stdClass $grade
+     * @param bool $showviewlink - Set to true to show a link to see the full list of files
+     * @return string
+     */
+    public function view_summary(stdClass $grade, $showviewlink) {
+        $count = $this->count_files($grade->id, ASSIGN_FILEAREA_FEEDBACK_FILES);
+        // show a view all link if the number of files is over this limit
+        $showviewlink = $count > ASSIGN_FEEDBACK_FILE_MAX_SUMMARY_FILES;
+
+        if ($count <= ASSIGN_FEEDBACK_FILE_MAX_SUMMARY_FILES) {
+            return $this->assignment->render_area_files('assignfeedback_file', ASSIGN_FILEAREA_FEEDBACK_FILES, $grade->id);
+        } else {
+            return get_string('countfiles', 'assignfeedback_file', $count);
+        }
+    }
+
+    /**
+     * Display the list of files  in the feedback status table
+     * @param stdClass $grade
+     * @return string
+     */
+    public function view(stdClass $grade) {
+        return $this->assignment->render_area_files('assignfeedback_file', ASSIGN_FILEAREA_FEEDBACK_FILES, $grade->id);
+    }
+
+    /**
+     * The assignment has been deleted - cleanup
+     *
+     * @return bool
+     */
+    public function delete_instance() {
+        global $DB;
+        // will throw exception on failure
+        $DB->delete_records('assignfeedback_file', array('assignment'=>$this->assignment->get_instance()->id));
+
+        return true;
+    }
+
+    /**
+     * Return true if there are no feedback files
+     * @param stdClass $grade
+     */
+    public function is_empty(stdClass $grade) {
+        return $this->count_files($grade->id, ASSIGN_FILEAREA_FEEDBACK_FILES) == 0;
+    }
+
+    /**
+     * Get file areas returns a list of areas this plugin stores files
+     * @return array - An array of fileareas (keys) and descriptions (values)
+     */
+    public function get_file_areas() {
+        return array(ASSIGN_FILEAREA_FEEDBACK_FILES=>$this->get_name());
+    }
+    
+    /**
+     * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
+     * and version.
+     *
+     * @param string $type old assignment subtype
+     * @param int $version old assignment version
+     * @return bool True if upgrade is possible
+     */
+    public function can_upgrade($type, $version) {
+
+        if (($type == 'upload' || $type == 'uploadsingle') && $version >= 2011112900) {
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Upgrade the settings from the old assignment to the new plugin based one
+     *
+     * @param context $oldcontext - the context for the old assignment
+     * @param stdClass $oldassignment - the data for the old assignment
+     * @param string $log - can be appended to by the upgrade
+     * @return bool was it a success? (false will trigger a rollback)
+     */
+    public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
+        // first upgrade settings (nothing to do)
+        return true;
+    }
+
+    /**
+     * Upgrade the feedback from the old assignment to the new one
+     *
+     * @param context $oldcontext - the database for the old assignment context
+     * @param stdClass $oldassignment The data record for the old assignment
+     * @param stdClass $oldsubmission The data record for the old submission
+     * @param stdClass $grade The data record for the new grade
+     * @param string $log Record upgrade messages in the log
+     * @return bool true or false - false will trigger a rollback
+     */
+    public function upgrade(context $oldcontext, stdClass $oldassignment, stdClass $oldsubmission, stdClass $grade, & $log) {
+        global $DB;
+
+        // now copy the area files
+        $this->assignment->copy_area_files_for_upgrade($oldcontext->id,
+                                                        'mod_assignment',
+                                                        'response',
+                                                        $oldsubmission->id,
+                                                        // New file area
+                                                        $this->assignment->get_context()->id,
+                                                        'assignfeedback_file',
+                                                        ASSIGN_FILEAREA_FEEDBACK_FILES,
+                                                        $grade->id);
+
+        // now count them!
+        $filefeedback = new stdClass();
+        $filefeedback->numfiles = $this->count_files($grade->id, ASSIGN_FILEAREA_FEEDBACK_FILES);
+        $filefeedback->grade = $grade->id;
+        $filefeedback->assignment = $this->assignment->get_instance()->id;
+        if (!$DB->insert_record('assignfeedback_file', $filefeedback) > 0) {
+            $log .= get_string('couldnotconvertgrade', 'mod_assign', $grade->userid);
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/mod/assign/feedback/file/version.php b/mod/assign/feedback/file/version.php
new file mode 100644 (file)
index 0000000..169b24b
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the version information for the comments feedback plugin
+ *
+ * @package assignfeedback_file
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$plugin->version   = 2012011600;
+$plugin->requires  = 2011110200;
+
+
+$plugin->component = 'assignfeedback_file';
+
diff --git a/mod/assign/feedbackplugin.php b/mod/assign/feedbackplugin.php
new file mode 100644 (file)
index 0000000..198900b
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the function for feedback_plugin abstract class
+ *
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/** Include assignmentplugin.php */
+require_once($CFG->dirroot.'/mod/assign/assignmentplugin.php');
+
+/**
+ * Abstract class for feedback_plugin inherited from assign_plugin abstract class.
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+abstract class assign_feedback_plugin extends assign_plugin {
+
+    /**
+     * return subtype name of the plugin
+     *
+     * @return string
+     */
+    public function get_subtype() {
+        return 'assignfeedback';
+    }
+
+    /**
+     * If this plugin adds to the gradebook comments field, it must specify the format
+     * of the comment
+     *
+     * (From weblib.php)
+     * define('FORMAT_MOODLE',   '0');   // Does all sorts of transformations and filtering
+     * define('FORMAT_HTML',     '1');   // Plain HTML (with some tags stripped)
+     * define('FORMAT_PLAIN',    '2');   // Plain text (even tags are printed in full)
+     * define('FORMAT_WIKI',     '3');   // Wiki-formatted text
+     * define('FORMAT_MARKDOWN', '4');   // Markdown-formatted
+     *
+     * Only one feedback plugin can push comments to the gradebook and that is chosen by the assignment
+     * settings page.
+     *
+     * @param stdClass $grade The grade
+     * @return int
+     */
+    public function format_for_gradebook(stdClass $grade) {
+        return FORMAT_MOODLE;
+    }
+
+    /**
+     * If this plugin adds to the gradebook comments field, it must format the text
+     * of the comment
+     *
+     * Only one feedback plugin can push comments to the gradebook and that is chosen by the assignment
+     * settings page.
+     *
+     * @param stdClass $grade The grade
+     * @return string
+     */
+    public function text_for_gradebook(stdClass $grade) {
+        return '';
+    }
+
+}
diff --git a/mod/assign/gradeform.php b/mod/assign/gradeform.php
new file mode 100644 (file)
index 0000000..f307a12
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the forms to create and edit an instance of this module
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
+
+
+/** Include formslib.php */
+require_once ($CFG->libdir.'/formslib.php');
+/** Include locallib.php */
+require_once($CFG->dirroot . '/mod/assign/locallib.php');
+/** Required for advanced grading */
+require_once('HTML/QuickForm/input.php');
+
+/**
+ * Assignment grade form
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_grade_form extends moodleform {
+    /** @var assignment $assignment */
+    private $assignment;
+
+    /**
+     * Define the form - called by parent constructor
+     */
+    function definition() {
+        $mform = $this->_form;
+
+        list($assignment, $data, $params) = $this->_customdata;
+        // visible elements
+        $this->assignment = $assignment;
+        $assignment->add_grade_form_elements($mform, $data, $params);
+
+        if ($data) {
+            $this->set_data($data);
+        }
+    }
+
+    /**
+     * Perform minimal validation on the grade form
+     * @param array $data
+     * @param array $files
+     */
+    function validation($data, $files) {
+        global $DB;
+        $errors = parent::validation($data, $files);
+        // advanced grading
+        if (!array_key_exists('grade', $data)) {
+            return $errors;
+        }
+
+        if ($this->assignment->get_instance()->grade > 0) {
+            if (!is_numeric($data['grade']) and (!empty($data['grade']))) {
+                $errors['grade'] = get_string('invalidfloatforgrade', 'assign', $data['grade']);
+            } else if ($data['grade'] > $this->assignment->get_instance()->grade) {
+                $errors['grade'] = get_string('gradeabovemaximum', 'assign', $this->assignment->get_instance()->grade);
+            } else if ($data['grade'] < 0) {
+                $errors['grade'] = get_string('gradebelowzero', 'assign');
+            }
+        } else {
+            // this is a scale
+            if ($scale = $DB->get_record('scale', array('id'=>-($this->assignment->get_instance()->grade)))) {
+                $scaleoptions = make_menu_from_list($scale->scale);
+                if (!array_key_exists((int)$data['grade'], $scaleoptions)) {
+                    $errors['grade'] = get_string('invalidgradeforscale', 'assign');
+                }
+            }
+        }
+        return $errors;
+    }
+
+}
diff --git a/mod/assign/gradingactionsform.php b/mod/assign/gradingactionsform.php
new file mode 100644 (file)
index 0000000..46eeda1
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the forms to create and edit an instance of this module
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
+
+
+/** Include formslib.php */
+require_once ($CFG->libdir.'/formslib.php');
+/** Include locallib.php */
+require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+/**
+ * Assignment grading actions form
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_grading_actions_form extends moodleform {
+    /**
+     * The definition for this form (called by the parent constructor)
+     */
+    function definition() {
+        $mform = $this->_form;
+        $data = $this->_customdata;
+        $links = $data['links'];
+        $cm = $data['cm'];
+        $mform->addElement('header', 'general', get_string('gradingactions', 'assign'));
+        // visible elements
+        $autosubmit = array('onchange'=>'form.submit();');
+        $mform->addElement('select', 'url', '', $links, $autosubmit);
+
+        // hidden params
+        $mform->addElement('hidden', 'id', $cm);
+        $mform->setType('id', PARAM_INT);
+        $mform->addElement('hidden', 'action', 'redirect');
+        $mform->setType('action', PARAM_ALPHA);
+
+        // buttons
+        $this->add_action_buttons(false, get_string('submitaction', 'assign'));
+    }
+}
diff --git a/mod/assign/gradingbatchoperationsform.php b/mod/assign/gradingbatchoperationsform.php
new file mode 100644 (file)
index 0000000..82d08b2
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the forms to create and edit an instance of this module
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
+
+
+/** Include formslib.php */
+require_once ($CFG->libdir.'/formslib.php');
+/** Include locallib.php */
+require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+/**
+ * Assignment grading options form
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_grading_batch_operations_form extends moodleform {
+    /**
+     * Define this form - called by the parent constructor
+     */
+    function definition() {
+        $mform = $this->_form;
+        $instance = $this->_customdata;
+
+        $mform->addElement('header', 'general', get_string('batchoperations', 'assign'));
+        // visible elements
+        $options = array();
+        $options['lock'] = get_string('locksubmissions', 'assign');
+        $options['unlock'] = get_string('unlocksubmissions', 'assign');
+        if ($instance['submissiondrafts']) {
+            $options['reverttodraft'] = get_string('reverttodraft', 'assign');
+        }
+        $mform->addElement('select', 'operation', get_string('batchoperationsdescription', 'assign'), $options, array('class'=>'operation'));
+        $mform->addHelpButton('operation', 'batchoperationsdescription', 'assign');
+        $mform->addElement('hidden', 'action', 'batchgradingoperation');
+        $mform->addElement('hidden', 'id', $instance['cm']);
+        $mform->addElement('hidden', 'selectedusers', '', array('class'=>'selectedusers'));
+        $mform->addElement('hidden', 'returnaction', 'grading');
+
+        $mform->addElement('submit', 'submit', get_string('submit'));
+    }
+
+}
+
diff --git a/mod/assign/gradingoptionsform.php b/mod/assign/gradingoptionsform.php
new file mode 100644 (file)
index 0000000..5d38834
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the forms to create and edit an instance of this module
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
+
+
+/** Include formslib.php */
+require_once ($CFG->libdir.'/formslib.php');
+/** Include locallib.php */
+require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+/**
+ * Assignment grading options form
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_grading_options_form extends moodleform {
+    /**
+     * Define this form - called from the parent constructor
+     */
+    function definition() {
+        $mform = $this->_form;
+        $instance = $this->_customdata;
+
+        $mform->addElement('header', 'general', get_string('gradingoptions', 'assign'));
+        // visible elements
+        $options = array(-1=>'All',10=>'10', 20=>'20', 50=>'50', 100=>'100');
+        $autosubmit = array('onchange'=>'form.submit();');
+        $mform->addElement('select', 'perpage', get_string('assignmentsperpage', 'assign'), $options, $autosubmit);
+        $options = array(''=>get_string('filternone', 'assign'), ASSIGN_FILTER_SUBMITTED=>get_string('filtersubmitted', 'assign'), ASSIGN_FILTER_REQUIRE_GRADING=>get_string('filterrequiregrading', 'assign'));
+        $mform->addElement('select', 'filter', get_string('filter', 'assign'), $options, $autosubmit);
+
+        // hidden params
+        $mform->addElement('hidden', 'contextid', $instance['contextid']);
+        $mform->setType('contextid', PARAM_INT);
+        $mform->addElement('hidden', 'id', $instance['cm']);
+        $mform->setType('id', PARAM_INT);
+        $mform->addElement('hidden', 'userid', $instance['userid']);
+        $mform->setType('userid', PARAM_INT);
+        $mform->addElement('hidden', 'action', 'saveoptions');
+        $mform->setType('action', PARAM_ALPHA);
+
+        // buttons
+        $this->add_action_buttons(false, get_string('updatetable', 'assign'));
+    }
+}
+
diff --git a/mod/assign/gradingtable.php b/mod/assign/gradingtable.php
new file mode 100644 (file)
index 0000000..e456e05
--- /dev/null
@@ -0,0 +1,653 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the definition for the grading table which subclassses easy_table
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->libdir.'/gradelib.php');
+require_once($CFG->dirroot.'/mod/assign/locallib.php');
+
+/**
+ * Extends table_sql to provide a table of assignment submissions
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class assign_grading_table extends table_sql implements renderable {
+    /** @var assign $assignment */
+    private $assignment = null;
+    /** @var int $perpage */
+    private $perpage = 10;
+    /** @var int $rownum (global index of current row in table) */
+    private $rownum = -1;
+    /** @var renderer_base for getting output */
+    private $output = null;
+    /** @var stdClass gradinginfo */
+    private $gradinginfo = null;
+    /** @var int $tablemaxrows */
+    private $tablemaxrows = 10000;
+
+    /**
+     * overridden constructor keeps a reference to the assignment class that is displaying this table
+     *
+     * @param assign $assignment The assignment class
+     * @param int $perpage how many per page
+     * @param string $filter The current filter
+     * @param int $rowoffset For showing a subsequent page of results
+     */
+    function __construct(assign $assignment, $perpage, $filter, $rowoffset=0) {
+        global $CFG, $PAGE;
+        parent::__construct('mod_assign_grading');
+        $this->assignment = $assignment;
+        $this->perpage = $perpage;
+        $this->output = $PAGE->get_renderer('mod_assign');
+
+        $this->define_baseurl(new moodle_url($CFG->wwwroot . '/mod/assign/view.php', array('action'=>'grading', 'id'=>$assignment->get_course_module()->id)));
+
+        // do some business - then set the sql
+
+        $currentgroup = groups_get_activity_group($assignment->get_course_module(), true);
+
+        if ($rowoffset) {
+            $this->rownum = $rowoffset - 1;
+        }
+
+        $users = array_keys( $assignment->list_participants($currentgroup, true));
+        if (count($users) == 0) {
+            // insert a record that will never match to the sql is still valid.
+            $users[] = -1;
+        }
+
+        $params = array();
+        $params[] = $this->assignment->get_instance()->id;
+        $params[] = $this->assignment->get_instance()->id;
+
+        $fields = user_picture::fields('u') . ', u.id as userid, u.firstname as firstname, u.lastname as lastname, ';
+        $fields .= 's.status as status, s.id as submissionid, s.timecreated as firstsubmission, s.timemodified as timesubmitted, ';
+        $fields .= 'g.id as gradeid, g.grade as grade, g.timemodified as timemarked, g.timecreated as firstmarked, g.mailed as mailed, g.locked as locked';
+        $from = '{user} u LEFT JOIN {assign_submission} s ON u.id = s.userid AND s.assignment = ?' . 
+                        ' LEFT JOIN {assign_grades} g ON u.id = g.userid AND g.assignment = ?';
+
+        $userparams = array();
+        foreach ($users as $userid) {
+            $userparams[] = '?';
+            $params[] = $userid;
+        }
+        
+        $where = 'u.id IN (' . implode(',', $userparams) . ')';
+        if ($filter == ASSIGN_FILTER_SUBMITTED) {
+            $where .= ' AND s.timecreated > 0 ';
+        }
+        if ($filter == ASSIGN_FILTER_REQUIRE_GRADING) {
+            $where .= ' AND (s.timemodified > g.timemodified OR g.timemodified IS NULL)';
+        }
+        if (strpos($filter, ASSIGN_FILTER_SINGLE_USER) === 0) {
+            $userfilter = (int) array_pop(explode('=', $filter));
+            $where .= ' AND (u.id = ?)';
+            $params[] = $userfilter;
+        }
+        $this->set_sql($fields, $from, $where, $params);
+
+        $columns = array();
+        $headers = array();
+
+        // Select
+        $columns[] = 'select';
+        $headers[] = get_string('select') . '<div class="selectall"><input type="checkbox" name="selectall" title="' . get_string('selectall') . '"/></div>';
+
+        // Edit links
+        if (!$this->is_downloading()) {
+            $columns[] = 'edit';
+            $headers[] = get_string('edit');
+        }
+
+        // User picture
+        $columns[] = 'picture';
+        $headers[] = get_string('pictureofuser');
+
+        // Fullname
+        $columns[] = 'fullname';
+        $headers[] = get_string('fullname');
+
+        // Submission status
+        if ($assignment->is_any_submission_plugin_enabled()) {
+            $columns[] = 'status';
+            $headers[] = get_string('status');
+        }
+
+
+        // Grade
+        $columns[] = 'grade';
+        $headers[] = get_string('grade');
+
+        // Submission plugins
+        if ($assignment->is_any_submission_plugin_enabled()) {
+            $columns[] = 'timesubmitted';
+            $headers[] = get_string('lastmodifiedsubmission', 'assign');
+
+            foreach ($this->assignment->get_submission_plugins() as $plugin) {
+                if ($plugin->is_visible() && $plugin->is_enabled()) {
+                    $columns[] = 'assignsubmission_' . $plugin->get_type();
+                    $headers[] = $plugin->get_name();
+                }
+            }
+        }
+
+        // time marked
+        $columns[] = 'timemarked';
+        $headers[] = get_string('lastmodifiedgrade', 'assign');
+
+        // Feedback plugins
+        foreach ($this->assignment->get_feedback_plugins() as $plugin) {
+            if ($plugin->is_visible() && $plugin->is_enabled()) {
+                $columns[] = 'assignfeedback_' . $plugin->get_type();
+                $headers[] = $plugin->get_name();
+            }
+        }
+
+        // final grade
+        $columns[] = 'finalgrade';
+        $headers[] = get_string('finalgrade', 'grades');
+
+
+
+        // set the columns
+        $this->define_columns($columns);
+        $this->define_headers($headers);
+        $this->no_sorting('finalgrade');
+        $this->no_sorting('edit');
+        $this->no_sorting('select');
+        foreach ($this->assignment->get_submission_plugins() as $plugin) {
+            if ($plugin->is_visible() && $plugin->is_enabled()) {
+                $this->no_sorting('assignsubmission_' . $plugin->get_type());
+            }
+        }
+        foreach ($this->assignment->get_feedback_plugins() as $plugin) {
+            if ($plugin->is_visible() && $plugin->is_enabled()) {
+                $this->no_sorting('assignfeedback_' . $plugin->get_type());
+            }
+        }
+
+        // load the grading info for all users
+        $this->gradinginfo = grade_get_grades($this->assignment->get_course()->id, 'mod', 'assign', $this->assignment->get_instance()->id, $users);
+    }
+
+    /**
+     * Add the userid to the row class so it can be updated via ajax
+     *
+     * @param stdClass $row The row of data
+     * @return string The row class
+     */
+    function get_row_class($row) {
+        return 'user' . $row->userid;
+    }
+
+    /**
+     * Return the number of rows to display on a single page
+     *
+     * @return int The number of rows per page
+     */
+    function get_rows_per_page() {
+        return $this->perpage;
+    }
+
+    /**
+     * Display a grade with scales etc.
+     *
+     * @param string $grade
+     * @return string The formatted grade
+     */
+    function display_grade($grade) {
+        if ($this->is_downloading()) {
+            return $grade;
+        }
+        $o = $this->assignment->display_grade($grade);
+
+        return $o;
+    }
+
+    /**
+     * Format a user picture for display (and update rownum as a sideeffect)
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_picture(stdClass $row) {
+        if ($row->picture) {
+            return $this->output->user_picture($row);
+        }
+        return '';
+    }
+
+    /**
+     * Format a user record for display (don't link to profile)
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_fullname($row) {
+        return fullname($row);
+    }
+
+    /**
+     * Insert a checkbox for selecting the current row for batch operations
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_select(stdClass $row) {
+        return '<input type="checkbox" name="selectedusers" value="' . $row->userid . '"/>';
+    }
+
+    /**
+     * Return a users grades from the listing of all grade data for this assignment
+     *
+     * @param int $userid
+     * @return mixed stdClass or false
+     */
+    private function get_gradebook_data_for_user($userid) {
+        if (isset($this->gradinginfo->items[0]) && $this->gradinginfo->items[0]->grades[$userid]) {
+            return $this->gradinginfo->items[0]->grades[$userid];
+        }
+        return false;
+    }
+
+    /**
+     * Format a column of data for display
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_grade(stdClass $row) {
+        $o = '';
+
+        $link = '';
+        $separator = '';
+        $grade = '';
+
+        if (!$this->is_downloading()) {
+            $icon = $this->output->pix_icon('gradefeedback', get_string('grade'), 'mod_assign');
+            $url = new moodle_url('/mod/assign/view.php',
+                                            array('id' => $this->assignment->get_course_module()->id,
+                                                  'rownum'=>$this->rownum,'action'=>'grade'));
+            $link = $this->output->action_link($url, $icon);
+            $separator = $this->output->spacer(array(), true);
+        }
+
+
+        if ($row->grade) {
+            $grade = $this->display_grade($row->grade);
+        } else {
+            $grade = '-';
+        }
+
+
+        //return $grade . $separator . $link;
+        return $link . $separator . $grade;
+    }
+
+    /**
+     * Format a column of data for display
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_finalgrade(stdClass $row) {
+        $o = '';
+
+        $grade = $this->get_gradebook_data_for_user($row->userid);
+        if ($grade) {
+            $o = $this->display_grade($grade->grade);
+        }
+
+        return $o;
+    }
+
+    /**
+     * Format a column of data for display
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_timemarked(stdClass $row) {
+        $o = '-';
+
+        if ($row->timemarked) {
+            $o = userdate($row->timemarked);
+        }
+
+        return $o;
+    }
+
+    /**
+     * Format a column of data for display
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_timesubmitted(stdClass $row) {
+        $o = '-';
+
+        if ($row->timesubmitted) {
+            $o = userdate($row->timesubmitted);
+        }
+
+        return $o;
+    }
+
+    /**
+     * Format a column of data for display
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_status(stdClass $row) {
+        $o = '';
+
+        if ($this->assignment->is_any_submission_plugin_enabled()) {
+
+            $o .= $this->output->container(get_string('submissionstatus_' . $row->status, 'assign'), array('class'=>'submissionstatus' .$row->status));
+            if ($this->assignment->get_instance()->duedate && $row->timesubmitted > $this->assignment->get_instance()->duedate) {
+                $o .= $this->output->container(get_string('submittedlateshort', 'assign', format_time($row->timesubmitted - $this->assignment->get_instance()->duedate)), 'latesubmission');
+            }
+            if ($row->locked) {
+                $o .= $this->output->container(get_string('submissionslockedshort', 'assign'), 'lockedsubmission');
+            }
+            if ($row->grade) {
+                $o .= $this->output->container(get_string('graded', 'assign'), 'submissiongraded');
+            }
+        }
+
+        return $o;
+    }
+
+    /**
+     * Format a column of data for display
+     *
+     * @param stdClass $row
+     * @return string
+     */
+    function col_edit(stdClass $row) {
+        $edit = '';
+        if ($this->rownum < 0) {
+            $this->rownum = $this->currpage * $this->pagesize;
+        } else {
+            $this->rownum += 1;
+        }
+
+        $actions = array();
+
+        $url = new moodle_url('/mod/assign/view.php',
+                                            array('id' => $this->assignment->get_course_module()->id,
+                                                  'rownum'=>$this->rownum,'action'=>'grade'));
+        if (!$row->grade) {
+           $description = get_string('grade');
+        }else{
+           $description = get_string('updategrade','assign');
+        }
+        $actions[$url->out(false)] = $description;
+
+        if (!$row->status || $row->status == ASSIGN_SUBMISSION_STATUS_DRAFT || !$this->assignment->get_instance()->submissiondrafts) {
+            if (!$row->locked) {
+                $url = new moodle_url('/mod/assign/view.php', array('id' => $this->assignment->get_course_module()->id,
+                                                                    'userid'=>$row->id,
+                                                                    'action'=>'lock',
+                                                                    'sesskey'=>sesskey(),
+                                                                    'page'=>$this->currpage));
+                $description = get_string('preventsubmissionsshort', 'assign');
+                $actions[$url->out(false)] = $description;
+            } else {
+                $url = new moodle_url('/mod/assign/view.php', array('id' => $this->assignment->get_course_module()->id,
+                                                                    'userid'=>$row->id,
+                                                                    'action'=>'unlock',
+                                                                    'sesskey'=>sesskey(),
+                                                                    'page'=>$this->currpage));
+                $description = get_string('allowsubmissionsshort', 'assign');
+                $actions[$url->out(false)] = $description;
+            }
+        }
+        if ($row->status == ASSIGN_SUBMISSION_STATUS_SUBMITTED && $this->assignment->get_instance()->submissiondrafts) {
+            $url = new moodle_url('/mod/assign/view.php', array('id' => $this->assignment->get_course_module()->id,
+                                                                'userid'=>$row->id,
+                                                                'action'=>'reverttodraft',
+                                                                'sesskey'=>sesskey(),
+                                                                'page'=>$this->currpage));
+            $description = get_string('reverttodraftshort', 'assign');
+            $actions[$url->out(false)] = $description;
+        }
+
+        $edit .= $this->output->container_start(array('yui3-menu', 'actionmenu'), 'actionselect' . $row->id);
+        $edit .= $this->output->container_start(array('yui3-menu-content'));
+        $edit .= html_writer::start_tag('ul');
+        $edit .= html_writer::start_tag('li', array('class'=>'menuicon'));
+
+        $menuicon = $this->output->pix_icon('i/menu', get_string('actions'));
+        $edit .= $this->output->action_link('#menu' . $row->id, $menuicon, null, array('class'=>'yui3-menu-label'));
+        $edit .= $this->output->container_start(array('yui3-menu', 'yui3-loading'), 'menu' . $row->id);
+        $edit .= $this->output->container_start(array('yui3-menu-content'));
+        $edit .= html_writer::start_tag('ul');
+
+        foreach ($actions as $url => $description) {
+            $edit .= html_writer::start_tag('li', array('class'=>'yui3-menuitem'));
+
+            $edit .= $this->output->action_link($url, $description, null, array('class'=>'yui3-menuitem-content'));
+
+            $edit .= html_writer::end_tag('li');
+        }
+        $edit .= html_writer::end_tag('ul');
+        $edit .= $this->output->container_end();
+        $edit .= $this->output->container_end();
+        $edit .= html_writer::end_tag('li');
+        $edit .= html_writer::end_tag('ul');
+
+        $edit .= $this->output->container_end();
+        $edit .= $this->output->container_end();
+
+        return $edit;
+    }
+
+    /**
+     * Write the plugin summary with an optional link to view the full feedback/submission.
+     *
+     * @param assign_plugin $plugin Submission plugin or feedback plugin
+     * @param stdClass $item Submission or grade
+     * @param string $returnaction The return action to pass to the view_submission page (the current page)
+     * @param string $returnparams The return params to pass to the view_submission page (the current page)
+     * @return string The summary with an optional link
+     */
+    private function format_plugin_summary_with_link(assign_plugin $plugin, stdClass $item, $returnaction, $returnparams) {
+        $link = '';
+        $showviewlink = false;
+        $summary = $plugin->view_summary($item, $showviewlink);
+        $separator = '';
+        if ($showviewlink) {
+            $icon = $this->output->pix_icon('t/preview', get_string('view' . substr($plugin->get_subtype(), strlen('assign')), 'mod_assign'));
+            $link = $this->output->action_link(
+                                new moodle_url('/mod/assign/view.php',
+                                               array('id' => $this->assignment->get_course_module()->id,
+                                                     'sid'=>$item->id,
+                                                     'gid'=>$item->id,
+                                                     'plugin'=>$plugin->get_type(),
+                                                     'action'=>'viewplugin' . $plugin->get_subtype(),
+                                                     'returnaction'=>$returnaction,
+                                                     'returnparams'=>http_build_query($returnparams))),
+                                $icon);
+            $separator = $this->output->spacer(array(), true);
+        }
+
+        return $link . $separator . $summary;
+    }
+
+
+    /**
+     * Format the submission and feedback columns
+     *
+     * @param string $colname The column name
+     * @param stdClass $row The submission row
+     * @return mixed string or NULL
+     */
+    function other_cols($colname, $row){
+        if (($pos = strpos($colname, 'assignsubmission_')) !== false) {
+            $plugin = $this->assignment->get_submission_plugin_by_type(substr($colname, strlen('assignsubmission_')));
+            if ($plugin->is_visible() && $plugin->is_enabled()) {
+                if ($row->submissionid) {
+                    $submission = new stdClass();
+                    $submission->id = $row->submissionid;
+                    $submission->timecreated = $row->firstsubmission;
+                    $submission->timemodified = $row->timesubmitted;
+                    $submission->assignment = $this->assignment->get_instance()->id;
+                    $submission->userid = $row->userid;
+
+                    return $this->format_plugin_summary_with_link($plugin, $submission, 'grading', array());
+                }
+            }
+            return '';
+        }
+        if (($pos = strpos($colname, 'feedback_')) !== false) {
+            $plugin = $this->assignment->get_feedback_plugin_by_type(substr($colname, strlen('assignfeedback_')));
+            if ($plugin->is_visible() && $plugin->is_enabled()) {
+                if ($row->gradeid) {
+                    $grade = new stdClass();
+                    $grade->id = $row->gradeid;
+                    $grade->timecreated = $row->firstmarked;
+                    $grade->timemodified = $row->timemarked;
+                    $grade->assignment = $this->assignment->get_instance()->id;
+                    $grade->userid = $row->userid;
+                    $grade->grade = $row->grade;
+                    $grade->mailed = $row->mailed;
+
+                    return $this->format_plugin_summary_with_link($plugin, $grade, 'grading', array());
+                }
+            }
+            return '';
+        }
+        return NULL;
+    }
+
+    /**
+     * Using the current filtering and sorting - load all rows and return a single column from them
+     *
+     * @param string $columnname The name of the raw column data
+     * @return array of data
+     */
+    function get_column_data($columnname) {
+        $this->setup();
+        $this->currpage = 0;
+        $this->query_db($this->tablemaxrows);
+        $result = array();
+        foreach ($this->rawdata as $row) {
+            $result[] = $row->$columnname;
+        }
+        return $result;
+    }
+    /**
+     * Using the current filtering and sorting - load a single row and return a single column from it
+     *
+     * @param int $rownumber The rownumber to load
+     * @param string $columnname The name of the raw column data
+     * @param bool $lastrow Set to true if this is the last row in the table
+     * @return mixed string or false
+     */
+    function get_cell_data($rownumber, $columnname, $lastrow) {
+        $this->setup();
+        $this->currpage = $rownumber;
+        $this->query_db(1);
+        if ($rownumber == $this->totalrows-1) {
+            $lastrow = true;
+        }
+        foreach ($this->rawdata as $row) {
+            return $row->$columnname;
+        }
+        return false;
+    }
+
+    /**
+     * Return things to the renderer
+     *
+     * @return string the assignment name
+     */
+    function get_assignment_name() {
+        return $this->assignment->get_instance()->name;
+    }
+
+    /**
+     * Return things to the renderer
+     *
+     * @return int the course module id
+     */
+    function get_course_module_id() {
+        return $this->assignment->get_course_module()->id;
+    }
+
+    /**
+     * Return things to the renderer
+     *
+     * @return int the course id
+     */
+    function get_course_id() {
+        return $this->assignment->get_course()->id;
+    }
+
+    /**
+     * Return things to the renderer
+     *
+     * @return stdClass The course context
+     */
+    function get_course_context() {
+        return $this->assignment->get_course_context();
+    }
+
+    /**
+     * Return things to the renderer
+     *
+     * @return bool Does this assignment accept submissions
+     */
+    function submissions_enabled() {
+        return $this->assignment->is_any_submission_plugin_enabled();
+    }
+
+    /**
+     * Return things to the renderer
+     *
+     * @return bool Can this user view all grades (the gradebook)
+     */
+    function can_view_all_grades() {
+        return has_capability('gradereport/grader:view', $this->assignment->get_course_context()) && has_capability('moodle/grade:viewall', $this->assignment->get_course_context());
+    }
+
+    /**
+     * Override the table show_hide_link to not show for select column
+     *
+     * @param string $column the column name, index into various names.
+     * @param int $index numerical index of the column.
+     * @return string HTML fragment.
+     */
+    protected function show_hide_link($column, $index) {
+        if ($index > 0) {
+            return parent::show_hide_link($column, $index);
+        }
+        return '';
+    }
+}
diff --git a/mod/assign/index.php b/mod/assign/index.php
new file mode 100644 (file)
index 0000000..cde25a4
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Displays information about all the assignment modules in the requested course
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once("../../config.php");
+require_once($CFG->dirroot.'/mod/assign/locallib.php');
+
+$id = required_param('id', PARAM_INT); // Course ID
+
+$course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);
+require_login($course);
+$PAGE->set_url('/mod/assign/index.php', array('id' => $id));
+$PAGE->set_pagelayout('incourse');
+
+add_to_log($course->id, "assign", "view all", "index.php?id=$course->id", "");
+
+// Print the header
+$strplural = get_string("modulenameplural", "assign");
+$PAGE->navbar->add($strplural);
+$PAGE->set_title($strplural);
+$PAGE->set_heading($course->fullname);
+echo $OUTPUT->header();
+
+// Get all the appropriate data
+if (!$assignments = get_all_instances_in_course("assign", $course)) {
+    notice(get_string('thereareno', 'moodle', $strplural), new moodle_url('/course/view.php', array('id' => $course->id)));
+    die;
+}
+
+// Check if we need the closing date header
+$table = new html_table();
+$table->head  = array ($strplural, get_string('duedate', 'assign'), get_string('submissions', 'assign'));
+$table->align = array ('left', 'left', 'center');
+$table->data = array();
+foreach ($assignments as $assignment) {
+    $cm = get_coursemodule_from_instance('assign', $assignment->id, 0, false, MUST_EXIST);
+
+    $link = html_writer::link(new moodle_url('/mod/assign/view.php', array('id' => $cm->id)), $assignment->name);
+    $date = userdate($assignment->duedate);
+    $submissions = $DB->count_records('assign_submission', array('assignment'=>$cm->instance));
+    $row = array($link, $date, $submissions);
+    $table->data[] = $row;
+
+}
+echo html_writer::table($table);
+echo $OUTPUT->footer();
diff --git a/mod/assign/lang/en/assign.php b/mod/assign/lang/en/assign.php
new file mode 100644 (file)
index 0000000..4c51755
--- /dev/null
@@ -0,0 +1,225 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Strings for component 'assign', language 'en'
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$string['allowsubmissions'] = 'Allow the user to continue making submissions to this assignment.';
+$string['allowsubmissionsshort'] = 'Allow submission changes';
+$string['allowsubmissionsfromdate'] = 'Allow submissions from';
+$string['allowsubmissionsfromdate_help'] = 'If enabled, students will not be able to submit before this date. If disabled, students will be able to start submitting right away.';
+$string['allowsubmissionsfromdatesummary'] = 'This assignment will accept submissions from <strong>{$a}</strong>';
+$string['allowsubmissionsanddescriptionfromdatesummary'] = 'The assignment details and submission form will be available from <strong>{$a}</strong>';
+$string['alwaysshowdescription'] = 'Always show description';
+$string['alwaysshowdescription_help'] = 'If disabled, the Assignment Description above will only become visible to students at the "Allow submissions from" date.';
+$string['assign:exportownsubmission'] = 'Export own submission';
+$string['assign:grade'] = 'Grade assignment';
+$string['assign:submit'] = 'Submit assignment';
+$string['assign:view'] = 'View assignment';
+$string['assignfeedback'] = 'Feedback plugin';
+$string['assignfeedbackpluginname'] = 'Feedback plugin';
+$string['assignmentisdue'] = 'Assignment is due';
+$string['assignmentmail'] = '{$a->grader} has posted some feedback on your
+assignment submission for \'{$a->assignment}\'
+
+You can see it appended to your assignment submission:
+
+    {$a->url}';
+$string['assignmentmailhtml'] = '{$a->grader} has posted some feedback on your
+assignment submission for \'<i>{$a->assignment}</i>\'<br /><br />
+You can see it appended to your <a href="{$a->url}">assignment submission</a>.';
+$string['assignmentmailsmall'] = '{$a->grader} has posted some feedback on your
+assignment submission for \'{$a->assignment}\' You can see it appended to your submission';
+$string['assignmentname'] = 'Assignment name';
+$string['assignmentplugins'] = 'Assignment plugins';
+$string['assignmentsperpage'] = 'Assignments per page';
+$string['assignsubmission'] = 'Submission plugin';
+$string['assignsubmissionpluginname'] = 'Submission plugin';
+$string['availability'] = 'Availability';
+$string['backtoassignment'] = 'Back to assignment';
+$string['batchoperations'] = 'Batch operations';
+$string['batchoperationsdescription'] = 'Perform action on selected row(s)';
+$string['batchoperationsdescription_help'] = 'The selected operation will be performed on all of the selected rows in the grading table. ';
+$string['batchoperationconfirmlock'] = 'Lock all selected submissions?';
+$string['batchoperationconfirmunlock'] = 'Unlock all selected submissions?';
+$string['batchoperationconfirmreverttodraft'] = 'Revert selected submissions to draft?';
+$string['batchoperationlock'] = 'lock submissions';
+$string['batchoperationunlock'] = 'unlock submissions';
+$string['batchoperationreverttodraft'] = 'revert submissions to draft';
+$string['comment'] = 'Comment';
+$string['conversionexception'] = 'Could not convert assignment. Exception was: {$a}.';
+$string['configshowrecentsubmissions'] = 'Everyone can see notifications of submissions in recent activity reports.';
+$string['confirmsubmission'] = 'Are you sure you want to submit your work for grading? You will not be able to make any more changes';
+$string['confirmbatchgradingoperation'] = 'Are you sure you want to {$a->operation} for {$a->count} students?';
+$string['couldnotconvertgrade'] = 'Could not convert assignment grade for user {$a}.';
+$string['couldnotconvertsubmission'] = 'Could not convert assignment submission for user {$a}.';
+$string['couldnotcreatecoursemodule'] = 'Could not create course module.';
+$string['couldnotcreatenewassignmentinstance'] = 'Could not create new assignment instance.';
+$string['couldnotfindassignmenttoupgrade'] = 'Could not find old assignment instance to upgrade.';
+$string['defaultplugins'] = 'Default assignment settings';
+$string['defaultplugins_help'] = 'These settings define the defaults for all new assignments.';
+$string['deletepluginareyousure'] = 'Delete assignment plugin {$a}: are you sure?';
+$string['deletepluginareyousuremessage'] = 'You are about to completely delete the assignment plugin {$a}. This will completely delete everything in the database associated with this assignment plugin. Are you SURE you want to continue?';
+$string['deletingplugin'] = 'Deleting plugin {$a}.';
+$string['description'] = 'Description';
+$string['downloadall'] = 'Download all submissions';
+$string['download all submissions'] = 'Download all submissions in a zip file.';
+$string['duedate'] = 'Due date';
+$string['duedate_help'] = 'This is when the assignment is due. If late submissions are allowed, any assignments submitted after this date are marked as late.';
+$string['duedateno'] = 'No due date';
+$string['duedatereached'] = 'The due date for this assignment has now passed';
+$string['duedatevalidation'] = 'Due date must be after the allow submissions from date.';
+$string['editsubmission'] = 'Edit my submission';
+$string['editaction'] = 'Actions...';
+$string['emailgradermail'] = '{$a->username} has updated their assignment submission
+for \'{$a->assignment}\' at {$a->timeupdated}
+
+It is available here:
+
+    {$a->url}';
+$string['emailgradermailhtml'] = '{$a->username} has updated their assignment submission
+for <i>\'{$a->assignment}\'  at {$a->timeupdated}</i><br /><br />
+It is <a href="{$a->url}">available on the web site</a>.';
+$string['enabled'] = 'Enabled';
+$string['errornosubmissions'] = 'There are no submissions to download';
+$string['feedbackcomments'] = 'Feedback comments';
+$string['feedback'] = 'Feedback';
+$string['feedbackplugins'] = 'Feedback plugins';
+$string['feedbackpluginforgradebook'] = 'Feedback plugin that will push comments to the gradebook';
+$string['feedbackplugin'] = 'Feedback plugin';
+$string['feedbacksettings'] = 'Feedback settings';
+$string['filesubmissions'] = 'File submissions';
+$string['filter'] = 'Filter';
+$string['filternone'] = 'No filter';
+$string['filterrequiregrading'] = 'Requires grading';
+$string['filtersubmitted'] = 'Submitted';
+$string['gradedby'] = 'Graded by';
+$string['graded'] = 'Graded';
+$string['gradedon'] = 'Graded on';
+$string['gradebelowzero'] = 'Grade must be greater than or equal to zero.';
+$string['gradeabovemaximum'] = 'Grade must be less than or equal to {$a}.';
+$string['gradeoutof'] = 'Grade out of {$a}';
+$string['gradeoutofhelp'] = 'Grade';
+$string['gradeoutofhelp_help'] = 'Enter the grade for the student\'s submission here. You may include decimals.';
+$string['gradestudent'] = 'Grade student: (id={$a->id}, fullname={$a->fullname}). ';
+$string['grading'] = 'Grading';
+$string['gradingoptions'] = 'Grade listing options';
+$string['gradingactions'] = 'Grading actions';
+$string['gradingstatus'] = 'Grading status';
+$string['gradingstudentprogress'] = 'Grading student {$a->index} of {$a->count}';
+$string['gradingsummary'] = 'Grading summary';
+$string['hideshow'] = 'Hide/Show';
+$string['instructionfiles'] = 'Instruction files';
+$string['invalidgradeforscale'] = 'The grade supplied was not valid for the current scale';
+$string['invalidfloatforgrade'] = 'The grade provided could not be understood: {$a}';
+$string['lastmodifiedsubmission'] = 'Last modified (submission)';
+$string['lastmodifiedgrade'] = 'Last modified (grade)';
+$string['locksubmissionforstudent'] = 'Prevent any more submissions for student: (id={$a->id}, fullname={$a->fullname}).';
+$string['locksubmissions'] = 'Lock submissions';
+$string['manageassignfeedbackplugins'] = 'Manage assignment feedback plugins';
+$string['manageassignsubmissionplugins'] = 'Manage assignment submission plugins';
+$string['messageprovider:assign_updates'] = 'Assignment notifications';
+$string['modulename'] = 'Assignment';
+$string['modulename_help'] = 'Assignments enable the teacher to specify a task either on or offline which can then be graded.';
+$string['modulenameplural'] = 'Assignments';
+$string['mysubmission'] = 'My submission: ';
+$string['newsubmissions'] = 'Assignments submitted';
+$string['nofiles'] = 'No files. ';
+$string['nograde'] = 'No grade. ';
+$string['noonlinesubmissions'] = 'This assignment does not require you to submit anything online';
+$string['nosavebutnext'] = 'Next';
+$string['nosubmission'] = 'Nothing has been submitted for this assignment';
+$string['notgraded'] = 'Not graded';
+$string['notgradedyet'] = 'Not graded yet';
+$string['notsubmittedyet'] = 'Not submitted yet';
+$string['notifications'] = 'Notifications';
+$string['nousersselected'] = 'No users selected';
+$string['numberofdraftsubmissions'] = 'Drafts';
+$string['numberofparticipants'] = 'Participants';
+$string['numberofsubmittedassignments'] = 'Submitted';
+$string['offline'] = 'No online submissions required';
+$string['overdue'] = '<font color="red">Assignment is overdue by: {$a}</font>';
+$string['outlinegrade'] = 'Grade: {$a}';
+$string['page-mod-assign-x'] = 'Any assignment module page';
+$string['page-mod-assign-view'] = 'Assignment module main and submission page';
+$string['pluginadministration'] = 'Assignment administration';
+$string['pluginname'] = 'Assignment';
+$string['preventlatesubmissions'] = 'Prevent late submissions';
+$string['preventlatesubmissions_help'] = 'If enabled, students will not be able submit after the Due Date. If disabled, students will be able to submit assignments after the due date and before the final date (if set).';
+$string['preventsubmissions'] = 'Prevent the user from making any more submissions to this assignment.';
+$string['preventsubmissionsshort'] = 'Prevent submission changes';
+$string['previous'] = 'Previous';
+$string['reverttodraftforstudent'] = 'Revert submission to draft for student: (id={$a->id}, fullname={$a->fullname}).';
+$string['reverttodraft'] = 'Revert the submission to draft status.';
+$string['reverttodraftshort'] = 'Revert the submission to draft';
+$string['reviewed'] = 'Reviewed';
+$string['savechanges'] = 'Save changes';
+$string['savenext'] = 'Save and show next';
+$string['sendnotifications'] = 'Send notifications to graders';
+$string['sendnotifications_help'] = 'If enabled, graders (usually teachers) receive a message whenever a student submits an assignment, early, on time and late. Message methods are configurable.';
+$string['selectlink'] = 'Select...';
+$string['settings'] = 'Assignment settings';
+$string['showrecentsubmissions'] = 'Show recent submissions';
+$string['submissiondrafts'] = 'Require students click submit button';
+$string['submissiondrafts_help'] = 'If enabled, students will have to click a Submit button to declare their submission as final. This allows students to keep a draft version of the submission on the system.';
+$string['submissionnotready'] = 'This assignment is not ready to submit:';
+$string['submissionplugins'] = 'Submission plugins';
+$string['submissionreceipts'] = 'Send submission receipts';
+$string['submissionslocked'] = 'This assignment is not accepting submissions';
+$string['submissionslockedshort'] = 'Submission changes not allowed';
+$string['submissions'] = 'Submissions';
+$string['submissionsnotgraded'] = 'Submissions not graded: {$a}';
+$string['submissionsclosed'] = 'Submissions closed';
+$string['submissionsettings'] = 'Submission settings';
+$string['submissionstatus_draft'] = 'Draft (not submitted)';
+$string['submissionstatusheading'] = 'Submission status';
+$string['submissionstatus_marked'] = 'Graded';
+$string['submissionstatus_new'] = 'New submission';
+$string['submissionstatus_'] = 'No submission';
+$string['submissionstatus'] = 'Submission status';
+$string['submissionstatus_submitted'] = 'Submitted for grading';
+$string['submission'] = 'Submission';
+$string['submitaction'] = 'Submit';
+$string['submitassignment_help'] = 'Once this assignment is submitted you will not be able to make any more changes';
+$string['submitassignment'] = 'Submit assignment';
+$string['submittedearly'] = 'Assignment was submitted {$a} early';
+$string['submittedlate'] = 'Assignment was submitted {$a} late';
+$string['submittedlateshort'] = '{$a} late';
+$string['submitted'] = 'Submitted';
+$string['textinstructions'] = 'Assignment instructions';
+$string['timemodified'] = 'Last modified';
+$string['timeremaining'] = 'Time remaining';
+$string['unlocksubmissionforstudent'] = 'Allow submissions for student: (id={$a->id}, fullname={$a->fullname}).';
+$string['unlocksubmissions'] = 'Unlock submissions';
+$string['updategrade'] = 'Update grade';
+$string['updatetable'] = 'Save and update table';
+$string['upgradenotimplemented'] = 'Upgrade not implemented in plugin ({$a->type} {$a->subtype})';
+$string['viewfeedback'] = 'View feedback';
+$string['viewfeedbackforuser'] = 'View feedback for user: {$a}';
+$string['viewfullgradingpage'] = 'Open the full grading page to provide feedback';
+$string['viewgradebook'] = 'View gradebook';
+$string['viewgradingformforstudent'] = 'View grading page for student: (id={$a->id}, fullname={$a->fullname}).';
+$string['viewgrading'] = 'View/grade all submissions';
+$string['viewownsubmissionform'] = 'View own submit assignment page.';
+$string['viewownsubmissionstatus'] = 'View own submission status page.';
+$string['viewsubmissionforuser'] = 'View submission for user: {$a}';
+$string['viewsubmission'] = 'View submission';
+$string['viewsubmissiongradingtable'] = 'View submission grading table.';
diff --git a/mod/assign/lib.php b/mod/assign/lib.php
new file mode 100644 (file)
index 0000000..10a3c33
--- /dev/null
@@ -0,0 +1,932 @@
+<?PHP
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the moodle hooks for the assign module. It delegates most functions to the assignment class.
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Adds an assignment instance
+ *
+ * This is done by calling the add_instance() method of the assignment type class
+ * @param stdClass $data
+ * @param mod_assign_mod_form $form
+ * @return int The instance id of the new assignment
+ */
+function assign_add_instance(stdClass $data, mod_assign_mod_form $form) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+    $assignment = new assign(context_module::instance($data->coursemodule), null, null);
+    return $assignment->add_instance($data, true);
+}
+
+/**
+ * delete an assignment instance
+ * @param int $id
+ * @return bool
+ */
+function assign_delete_instance($id) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    $cm = get_coursemodule_from_instance('assign', $id, 0, false, MUST_EXIST);
+    $context = context_module::instance($cm->id);
+
+    $assignment = new assign($context, null, null);
+    return $assignment->delete_instance();
+}
+
+/**
+ * Update an assignment instance
+ *
+ * This is done by calling the update_instance() method of the assignment type class
+ * @param stdClass $data
+ * @param mod_assign_mod_form $form
+ * @return object
+ */
+function assign_update_instance(stdClass $data, mod_assign_mod_form $form) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    $context = context_module::instance($data->coursemodule);
+    $assignment = new assign($context, null, null);
+    return $assignment->update_instance($data);
+}
+
+/**
+ * Return the list if Moodle features this module supports
+ *
+ * @param string $feature FEATURE_xx constant for requested feature
+ * @return mixed True if module supports feature, null if doesn't know
+ */
+function assign_supports($feature) {
+    switch($feature) {
+        case FEATURE_GROUPS:                  return true;
+        case FEATURE_GROUPINGS:               return true;
+        case FEATURE_GROUPMEMBERSONLY:        return true;
+        case FEATURE_MOD_INTRO:               return true;
+        case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
+        case FEATURE_GRADE_HAS_GRADE:         return true;
+        case FEATURE_GRADE_OUTCOMES:          return true;
+        case FEATURE_BACKUP_MOODLE2:          return true;
+        case FEATURE_SHOW_DESCRIPTION:        return true;
+        case FEATURE_ADVANCED_GRADING:        return true;
+
+        default: return null;
+    }
+}
+
+/**
+ * Lists all gradable areas for the advanced grading methods gramework
+ *
+ * @return array('string'=>'string') An array with area names as keys and descriptions as values
+ */
+function assign_grading_areas_list() {
+    return array('submissions'=>get_string('submissions', 'assign'));
+}
+
+
+/**
+ * extend an assigment navigation settings
+ *
+ * @param settings_navigation $settings
+ * @param navigation_node $navref
+ * @return void
+ */
+function assign_extend_settings_navigation(settings_navigation $settings, navigation_node $navref) {
+    global $PAGE;
+
+    $cm = $PAGE->cm;
+    if (!$cm) {
+        return;
+    }
+
+    $context = $cm->context;
+    $course = $PAGE->course;
+
+
+    if (!$course) {
+        return;
+    }
+
+
+   // Link to gradebook
+   if (has_capability('gradereport/grader:view', $cm->context) && has_capability('moodle/grade:viewall', $cm->context)) {
+       $link = new moodle_url('/grade/report/grader/index.php', array('id' => $course->id));
+       $node = $navref->add(get_string('viewgradebook', 'assign'), $link, navigation_node::TYPE_SETTING);
+   }
+
+   // Link to download all submissions
+   if (has_capability('mod/assign:grade', $context)) {
+       $link = new moodle_url('/mod/assign/view.php', array('id' => $cm->id,'action'=>'grading'));
+       $node = $navref->add(get_string('viewgrading', 'assign'), $link, navigation_node::TYPE_SETTING);
+
+       $link = new moodle_url('/mod/assign/view.php', array('id' => $cm->id,'action'=>'downloadall'));
+       $node = $navref->add(get_string('downloadall', 'assign'), $link, navigation_node::TYPE_SETTING);
+   }
+
+}
+
+
+/**
+ * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information
+ * for the course (see resource).
+ *
+ * Given a course_module object, this function returns any "extra" information that may be needed
+ * when printing this activity in a course listing.  See get_array_of_activities() in course/lib.php.
+ *
+ * @param stdClass $coursemodule The coursemodule object (record).
+ * @return cached_cm_info An object on information that the courses will know about (most noticeably, an icon).
+ */
+function assign_get_coursemodule_info($coursemodule) {
+    global $CFG, $DB;
+
+    if (! $assignment = $DB->get_record('assign', array('id'=>$coursemodule->instance),
+            'id, name, alwaysshowdescription, allowsubmissionsfromdate, intro, introformat')) {
+        return false;
+    }
+
+    $result = new cached_cm_info();
+    $result->name = $assignment->name;
+    if ($coursemodule->showdescription) {
+        if ($assignment->alwaysshowdescription || time() > $assignment->allowsubmissionsfromdate) {
+            // Convert intro to html. Do not filter cached version, filters run at display time.
+            $result->content = format_module_intro('assign', $assignment, $coursemodule->id, false);
+        }
+    }
+    return $result;
+}
+
+
+/**
+ * Return a list of page types
+ * @param string $pagetype current page type
+ * @param stdClass $parentcontext Block's parent context
+ * @param stdClass $currentcontext Current context of block
+ */
+function assign_page_type_list($pagetype, $parentcontext, $currentcontext) {
+    $module_pagetype = array(
+        'mod-assign-*' => get_string('page-mod-assign-x', 'assign'),
+        'mod-assign-view' => get_string('page-mod-assign-view', 'assign'),
+    );
+    return $module_pagetype;
+}
+
+/**
+ * Print an overview of all assignments
+ * for the courses.
+ *
+ * @param mixed $courses The list of courses to print the overview for
+ * @param array $htmlarray The array of html to return
+ */
+function assign_print_overview($courses, &$htmlarray) {
+    global $USER, $CFG, $DB;
+
+    if (empty($courses) || !is_array($courses) || count($courses) == 0) {
+        return array();
+    }
+
+    if (!$assignments = get_all_instances_in_courses('assign',$courses)) {
+        return;
+    }
+
+    $assignmentids = array();
+
+    // Do assignment_base::isopen() here without loading the whole thing for speed
+    foreach ($assignments as $key => $assignment) {
+        $time = time();
+        if ($assignment->duedate) {
+            if ($assignment->preventlatesubmissions) {
+                $isopen = ($assignment->allowsubmissionsfromdate <= $time && $time <= $assignment->duedate);
+            } else {
+                $isopen = ($assignment->allowsubmissionsfromdate <= $time);
+            }
+        }
+        if (empty($isopen) || empty($assignment->duedate)) {
+            $assignmentids[] = $assignment->id;
+        } else {
+            $assignmentids[] = $assignment->id;
+        }
+    }
+
+    if (empty($assignmentids)){
+        // no assignments to look at - we're done
+        return true;
+    }
+
+    $strduedate = get_string('duedate', 'assign');
+    $strduedateno = get_string('duedateno', 'assign');
+    $strgraded = get_string('graded', 'assign');
+    $strnotgradedyet = get_string('notgradedyet', 'assign');
+    $strnotsubmittedyet = get_string('notsubmittedyet', 'assign');
+    $strsubmitted = get_string('submitted', 'assign');
+    $strassignment = get_string('modulename', 'assign');
+    $strreviewed = get_string('reviewed','assign');
+
+
+    // NOTE: we do all possible database work here *outside* of the loop to ensure this scales
+    //
+    list($sqlassignmentids, $assignmentidparams) = $DB->get_in_or_equal($assignmentids);
+
+    // build up and array of unmarked submissions indexed by assignment id/ userid
+    // for use where the user has grading rights on assignment
+    $rs = $DB->get_recordset_sql("SELECT s.assignment as assignment, s.userid as userid, s.id as id, s.status as status, g.timemodified as timegraded
+                            FROM {assign_submission} s LEFT JOIN {assign_grades} g ON s.userid = g.userid and s.assignment = g.assignment
+                            WHERE g.timemodified = 0 OR s.timemodified > g.timemodified
+                            AND s.assignment $sqlassignmentids", $assignmentidparams);
+
+    $unmarkedsubmissions = array();
+    foreach ($rs as $rd) {
+        $unmarkedsubmissions[$rd->assignment][$rd->userid] = $rd->id;
+    }
+    $rs->close();
+
+
+    // get all user submissions, indexed by assignment id
+    $mysubmissions = $DB->get_records_sql("SELECT a.id AS assignment, a.nosubmissions AS offline, g.timemodified AS timemarked, g.grader AS grader, g.grade AS grade, s.status AS status
+                            FROM {assign} a LEFT JOIN {assign_grades} g ON g.assignment = a.id AND g.userid = ? LEFT JOIN {assign_submission} s ON s.assignment = a.id AND s.userid = ?
+                            AND a.id $sqlassignmentids", array_merge(array($USER->id, $USER->id), $assignmentidparams));
+
+    foreach ($assignments as $assignment) {
+        $str = '<div class="assign overview"><div class="name">'.$strassignment. ': '.
+               '<a '.($assignment->visible ? '':' class="dimmed"').
+               'title="'.$strassignment.'" href="'.$CFG->wwwroot.
+               '/mod/assign/view.php?id='.$assignment->coursemodule.'">'.
+               format_string($assignment->name).'</a></div>';
+        if ($assignment->duedate) {
+            $str .= '<div class="info">'.$strduedate.': '.userdate($assignment->duedate).'</div>';
+        } else {
+            $str .= '<div class="info">'.$strduedateno.'</div>';
+        }
+        $context = context_module::instance($assignment->coursemodule);
+        if (has_capability('mod/assign:grade', $context)) {
+
+            // count how many people can submit
+            $submissions = 0; // init
+            if ($students = get_enrolled_users($context, 'mod/assign:view', 0, 'u.id')) {
+                foreach ($students as $student) {
+                    if (isset($unmarkedsubmissions[$assignment->id][$student->id])) {
+                        $submissions++;
+                    }
+                }
+            }
+
+            if ($submissions) {
+                $link = new moodle_url('/mod/assign/view.php', array('id'=>$assignment->coursemodule, 'action'=>'grading'));
+                $str .= '<div class="details"><a href="'.$link.'">'.get_string('submissionsnotgraded', 'assign', $submissions).'</a></div>';
+            }
+        } if (has_capability('mod/assign:submit', $context)) {
+            $str .= '<div class="details">';
+            $str .= get_string('mysubmission', 'assign');
+            $submission = $mysubmissions[$assignment->id];
+            if ($submission->offline) {
+                 $str .= get_string('offline', 'assign');
+            } else if(!$submission->status || $submission->status == 'draft'){
+                 $str .= $strnotsubmittedyet;
+            }else {
+                $str .= get_string('submissionstatus_' . $submission->status, 'assign');
+            }
+            if (!$submission->grade || $submission->grade < 0) {
+                $str .= ', ' . get_string('notgraded', 'assign');
+            } else {
+                $str .= ', ' . get_string('graded', 'assign');
+            }
+            $str .= '</div>';
+        }
+       $str .= '</div>';
+        if (empty($htmlarray[$assignment->course]['assign'])) {
+            $htmlarray[$assignment->course]['assign'] = $str;
+        } else {
+            $htmlarray[$assignment->course]['assign'] .= $str;
+        }
+    }
+}
+
+/**
+ * Print recent activity from all assignments in a given course
+ *
+ * This is used by the recent activity block
+ * @param mixed $course the course to print activity for
+ * @param bool $viewfullnames boolean to determine whether to show full names or not
+ * @param int $timestart the time the rendering started 
+ */
+function assign_print_recent_activity($course, $viewfullnames, $timestart) {
+    global $CFG, $USER, $DB, $OUTPUT;
+
+    // do not use log table if possible, it may be huge
+
+    if (!$submissions = $DB->get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid, asb.userid,
+                                                     u.firstname, u.lastname, u.email, u.picture
+                                                FROM {assign_submission} asb
+                                                     JOIN {assign} a      ON a.id = asb.assignment
+                                                     JOIN {course_modules} cm ON cm.instance = a.id
+                                                     JOIN {modules} md        ON md.id = cm.module
+                                                     JOIN {user} u            ON u.id = asb.userid
+                                               WHERE asb.timemodified > ? AND
+                                                     a.course = ? AND
+                                                     md.name = 'assign'
+                                            ORDER BY asb.timemodified ASC", array($timestart, $course->id))) {
+         return false;
+    }
+
+    $modinfo = get_fast_modinfo($course); // no need pass this by reference as the return object already being cached
+    $show    = array();
+    $grader  = array();
+
+    foreach($submissions as $submission) {
+        if (!array_key_exists($submission->cmid, $modinfo->get_cms())) {
+            continue;
+        }
+        $cm = $modinfo->get_cm($submission->cmid);
+        if (!$cm->uservisible) {
+            continue;
+        }
+        if ($submission->userid == $USER->id) {
+            $show[] = $submission;
+            continue;
+        }
+
+        $context = context_module::instance($submission->cmid);
+        // the act of sumbitting of assignment may be considered private - only graders will see it if specified
+        if (empty($CFG->assign_showrecentsubmissions)) {
+            if (!array_key_exists($cm->id, $grader)) {
+                $grader[$cm->id] = has_capability('moodle/grade:viewall',$context);
+            }
+            if (!$grader[$cm->id]) {
+                continue;
+            }
+        }
+
+        $groupmode = groups_get_activity_groupmode($cm, $course);
+
+        if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups',  $context)) {
+            if (isguestuser()) {
+                // shortcut - guest user does not belong into any group
+                continue;
+            }
+
+            if (is_null($modinfo->get_groups())) {
+                $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
+            }
+
+            // this will be slow - show only users that share group with me in this cm
+            if (empty($modinfo->groups[$cm->id])) {
+                continue;
+            }
+            $usersgroups =  groups_get_all_groups($course->id, $submission->userid, $cm->groupingid);
+            if (is_array($usersgroups)) {
+                $usersgroups = array_keys($usersgroups);
+                $intersect = array_intersect($usersgroups, $modinfo->groups[$cm->id]);
+                if (empty($intersect)) {
+                    continue;
+                }
+            }
+        }
+        $show[] = $submission;
+    }
+
+    if (empty($show)) {
+        return false;
+    }
+
+    echo $OUTPUT->heading(get_string('newsubmissions', 'assign').':', 3);
+
+    foreach ($show as $submission) {
+        $cm = $modinfo->get_cm($submission->cmid);
+        $link = $CFG->wwwroot.'/mod/assign/view.php?id='.$cm->id;
+        print_recent_activity_note($submission->timemodified, $submission, $cm->name, $link, false, $viewfullnames);
+    }
+
+    return true;
+}
+
+/**
+ * Returns all assignments since a given time
+ * 
+ * @param array $activities The activity information is returned in this array
+ * @param int $index The current index in the activities array
+ * @param int $timestart The earliest activity to show
+ * @param int $courseid Limit the search to this course
+ * @param int $cmid The course module id
+ * @param int $userid Optional user id
+ * @param int $groupid Optional group id
+ * @return void
+ */
+function assign_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0)  {
+    global $CFG, $COURSE, $USER, $DB;
+
+    if ($COURSE->id == $courseid) {
+        $course = $COURSE;
+    } else {
+        $course = $DB->get_record('course', array('id'=>$courseid));
+    }
+
+    $modinfo = get_fast_modinfo($course); // no need pass this by reference as the return object already being cached
+
+    $cm = $modinfo->get_cm($cmid);
+    $params = array();
+    if ($userid) {
+        $userselect = "AND u.id = :userid";
+        $params['userid'] = $userid;
+    } else {
+        $userselect = "";
+    }
+
+    if ($groupid) {
+        $groupselect = "AND gm.groupid = :groupid";
+        $groupjoin   = "JOIN {groups_members} gm ON  gm.userid=u.id";
+        $params['groupid'] = $groupid;
+    } else {
+        $groupselect = "";
+        $groupjoin   = "";
+    }
+
+    $params['cminstance'] = $cm->instance;
+    $params['timestart'] = $timestart;
+
+    $userfields = user_picture::fields('u', null, 'userid');
+
+    if (!$submissions = $DB->get_records_sql("SELECT asb.id, asb.timemodified,
+                                                     $userfields
+                                                FROM {assign_submission} asb
+                                                JOIN {assign} a      ON a.id = asb.assignment
+                                                JOIN {user} u            ON u.id = asb.userid
+                                          $groupjoin
+                                               WHERE asb.timemodified > :timestart AND a.id = :cminstance
+                                                     $userselect $groupselect
+                                            ORDER BY asb.timemodified ASC", $params)) {
+         return;
+    }
+
+    $groupmode       = groups_get_activity_groupmode($cm, $course);
+    $cm_context      = context_module::instance($cm->id);
+    $grader          = has_capability('moodle/grade:viewall', $cm_context);
+    $accessallgroups = has_capability('moodle/site:accessallgroups', $cm_context);
+    $viewfullnames   = has_capability('moodle/site:viewfullnames', $cm_context);
+
+    if (is_null($modinfo->get_groups())) {
+        $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
+    }
+
+    $show = array();
+    $usersgroups = groups_get_all_groups($course->id, $USER->id, $cm->groupingid);
+    if (is_array($usersgroups)) {
+        $usersgroups = array_keys($usersgroups);
+    }
+    foreach($submissions as $submission) {
+        if ($submission->userid == $USER->id) {
+            $show[] = $submission;
+            continue;
+        }
+        // the act of submitting of assignment may be considered private - only graders will see it if specified
+        if (empty($CFG->assign_showrecentsubmissions)) {
+            if (!$grader) {
+                continue;
+            }
+        }
+
+        if ($groupmode == SEPARATEGROUPS and !$accessallgroups) {
+            if (isguestuser()) {
+                // shortcut - guest user does not belong into any group
+                continue;
+            }
+
+            // this will be slow - show only users that share group with me in this cm
+            if (empty($modinfo->groups[$cm->id])) {
+                continue;
+            }
+            if (is_array($usersgroups)) {
+                $intersect = array_intersect($usersgroups, $modinfo->groups[$cm->id]);
+                if (empty($intersect)) {
+                    continue;
+                }
+            }
+        }
+        $show[] = $submission;
+    }
+
+    if (empty($show)) {
+        return;
+    }
+
+    if ($grader) {
+        require_once($CFG->libdir.'/gradelib.php');
+        $userids = array();
+        foreach ($show as $id=>$submission) {
+            $userids[] = $submission->userid;
+
+        }
+        $grades = grade_get_grades($courseid, 'mod', 'assign', $cm->instance, $userids);
+    }
+
+    $aname = format_string($cm->name,true);
+    foreach ($show as $submission) {
+        $activity = new stdClass();
+
+        $activity->type         = 'assign';
+        $activity->cmid         = $cm->id;
+        $activity->name         = $aname;
+        $activity->sectionnum   = $cm->sectionnum;
+        $activity->timestamp    = $submission->timemodified;
+        $activity->user         = new stdClass();
+        if ($grader) {
+            $activity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade;
+        }
+
+        $userfields = explode(',', user_picture::fields());
+        foreach ($userfields as $userfield) {
+            if ($userfield == 'id') {
+                $activity->user->{$userfield} = $submission->userid; // aliased in SQL above
+            } else {
+                $activity->user->{$userfield} = $submission->{$userfield};
+            }
+        }
+        $activity->user->fullname = fullname($submission, $viewfullnames);
+
+        $activities[$index++] = $activity;
+    }
+
+    return;
+}
+
+/**
+ * Print recent activity from all assignments in a given course
+ *
+ * This is used by course/recent.php
+ * @param stdClass $activity
+ * @param int $courseid
+ * @param bool $detail
+ * @param array $modnames
+ */
+function assign_print_recent_mod_activity($activity, $courseid, $detail, $modnames)  {
+    global $CFG, $OUTPUT;
+
+    echo '<table border="0" cellpadding="3" cellspacing="0" class="assignment-recent">';
+
+    echo "<tr><td class=\"userpicture\" valign=\"top\">";
+    echo $OUTPUT->user_picture($activity->user);
+    echo "</td><td>";
+
+    if ($detail) {
+        $modname = $modnames[$activity->type];
+        echo '<div class="title">';
+        echo "<img src=\"" . $OUTPUT->pix_url('icon', 'assign') . "\" ".
+             "class=\"icon\" alt=\"$modname\">";
+        echo "<a href=\"$CFG->wwwroot/mod/assign/view.php?id={$activity->cmid}\">{$activity->name}</a>";
+        echo '</div>';
+    }
+
+    if (isset($activity->grade)) {
+        echo '<div class="grade">';
+        echo get_string('grade').': ';
+        echo $activity->grade;
+        echo '</div>';
+    }
+
+    echo '<div class="user">';
+    echo "<a href=\"$CFG->wwwroot/user/view.php?id={$activity->user->id}&amp;course=$courseid\">"
+         ."{$activity->user->fullname}</a>  - ".userdate($activity->timestamp);
+    echo '</div>';
+
+    echo "</td></tr></table>";
+}
+
+/**
+ * Checks if a scale is being used by an assignment
+ *
+ * This is used by the backup code to decide whether to back up a scale
+ * @param int $assignmentid 
+ * @param int $scaleid
+ * @return boolean True if the scale is used by the assignment
+ */
+function assign_scale_used($assignmentid, $scaleid) {
+    global $DB;
+
+    $return = false;
+    $rec = $DB->get_record('assign', array('id'=>$assignmentid,'grade'=>-$scaleid));
+
+    if (!empty($rec) && !empty($scaleid)) {
+        $return = true;
+    }
+
+    return $return;
+}
+
+/**
+ * Checks if scale is being used by any instance of assignment
+ *
+ * This is used to find out if scale used anywhere
+ * @param int $scaleid 
+ * @return boolean True if the scale is used by any assignment
+ */
+function assign_scale_used_anywhere($scaleid) {
+    global $DB;
+
+    if ($scaleid and $DB->record_exists('assign', array('grade'=>-$scaleid))) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/**
+ * function to list the actions that correspond to a view of this module
+ * This is used by the participation report
+ * @return array
+ */
+function assign_get_view_actions() {
+    return array('view submission', 'view feedback');
+}
+
+/**
+ * function to list the actions that correspond to a post of this module
+ * This is used by the participation report
+ * @return array
+ */
+function assign_get_post_actions() {
+    return array('upload', 'submit', 'submit for grading');
+}
+
+/**
+ * Call cron on the assign module
+ */
+function assign_cron() {
+    global $CFG;
+
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    //assignment::cron();
+    $plugins = get_plugin_list('assignsubmission');
+
+    foreach ($plugins as $name => $plugin) {
+        $disabled = get_config('assignsubmission_' . $name, 'disabled');
+        if (!$disabled) {
+            $class = 'assign_submission_' . $name;
+            require_once($CFG->dirroot . '/mod/assign/submission/' . $name . '/locallib.php');
+            $class::cron();
+        }
+    }
+    $plugins = get_plugin_list('assignfeedback');
+
+    foreach ($plugins as $name => $plugin) {
+        $disabled = get_config('assignfeedback_' . $name, 'disabled');
+        if (!$disabled) {
+            $class = 'assign_feedback_' . $name;
+            require_once($CFG->dirroot . '/mod/assign/feedback/' . $name . '/locallib.php');
+            $class::cron();
+        }
+    }
+}
+
+/**
+ * Returns all other capabilities used by this module.
+ * @return array Array of capability strings
+ */
+function assign_get_extra_capabilities() {
+    return array('gradereport/grader:view', 'moodle/grade:viewall', 'moodle/site:viewfullnames', 'moodle/site:config');
+}
+
+/**
+ * Create grade item for given assignment
+ *
+ * @param stdClass $assign record with extra cmidnumber
+ * @param array $grades optional array/object of grade(s); 'reset' means reset grades in gradebook
+ * @return int 0 if ok, error code otherwise
+ */
+function assign_grade_item_update($assign, $grades=NULL) {
+    global $CFG;
+    require_once($CFG->libdir.'/gradelib.php');
+
+    if (!isset($assign->courseid)) {
+        $assign->courseid = $assign->course;
+    }
+
+    $params = array('itemname'=>$assign->name, 'idnumber'=>$assign->cmidnumber);
+
+    if ($assign->grade > 0) {
+        $params['gradetype'] = GRADE_TYPE_VALUE;
+        $params['grademax']  = $assign->grade;
+        $params['grademin']  = 0;
+
+    } else if ($assign->grade < 0) {
+        $params['gradetype'] = GRADE_TYPE_SCALE;
+        $params['scaleid']   = -$assign->grade;
+
+    } else {
+        $params['gradetype'] = GRADE_TYPE_TEXT; // allow text comments only
+    }
+
+    if ($grades  === 'reset') {
+        $params['reset'] = true;
+        $grades = NULL;
+    }
+
+    return grade_update('mod/assign', $assign->courseid, 'mod', 'assign', $assign->id, 0, $grades, $params);
+}
+
+/**
+ * Return grade for given user or all users.
+ *
+ * @param stdClass $assign record of assign with an additional cmidnumber
+ * @param int $userid optional user id, 0 means all users
+ * @return array array of grades, false if none
+ */
+function assign_get_user_grades($assign, $userid=0) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+    $context = context_module::instance($assign->cmidnumber);
+    $assignment = new assign($context, null, null);
+    return $assignment->get_user_grades_for_gradebook($userid);
+}
+
+/**
+ * Update activity grades
+ *
+ * @param stdClass $assign database record
+ * @param int $userid specific user only, 0 means all
+ * @param bool $nullifnone - not used
+ */
+function assign_update_grades($assign, $userid=0, $nullifnone=true) {
+    global $CFG;
+    require_once($CFG->libdir.'/gradelib.php');
+
+    if ($assign->grade == 0) {
+        assign_grade_item_update($assign);
+
+    } else if ($grades = assign_get_user_grades($assign, $userid)) {
+        foreach($grades as $k=>$v) {
+            if ($v->rawgrade == -1) {
+                $grades[$k]->rawgrade = null;
+            }
+        }
+        assign_grade_item_update($assign, $grades);
+
+    } else {
+        assign_grade_item_update($assign);
+    }
+}
+
+/**
+ * List the file areas that can be browsed
+ *
+ * @param stdClass $course
+ * @param stdClass $cm
+ * @param stdClass $context
+ * @return array
+ */
+function mod_assign_get_file_areas($course, $cm, $context) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    $areas = array();
+
+    $assignment = new assign($context, $cm, $course);
+    foreach ($assignment->get_submission_plugins() as $plugin) {
+        if ($plugin->is_visible()) {
+            $pluginareas = $plugin->get_file_areas();
+
+            if ($pluginareas) {
+                $areas = array_merge($areas, $pluginareas);
+            }
+        }
+    }
+    foreach ($assignment->get_feedback_plugins() as $plugin) {
+        if ($plugin->is_visible()) {
+            $pluginareas = $plugin->get_file_areas();
+
+            if ($pluginareas) {
+                $areas = array_merge($areas, $pluginareas);
+            }
+        }
+    }
+
+    return $areas;
+}
+
+/**
+ * File browsing support for assign module.
+ *
+ * @param file_browser $browser
+ * @param object $areas
+ * @param object $course
+ * @param object $cm
+ * @param object $context
+ * @param string $filearea
+ * @param int $itemid
+ * @param string $filepath
+ * @param string $filename
+ * @return object file_info instance or null if not found
+ */
+function mod_assign_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+
+    if ($context->contextlevel != CONTEXT_MODULE) {
+        return null;
+    }
+
+    $fs = get_file_storage();
+    $filepath = is_null($filepath) ? '/' : $filepath;
+    $filename = is_null($filename) ? '.' : $filename;
+
+    // need to find the plugin this belongs to
+    $assignment = new assign($context, $cm, $course);
+    $pluginowner = null;
+    foreach ($assignment->get_submission_plugins() as $plugin) {
+        if ($plugin->is_visible()) {
+            $pluginareas = $plugin->get_file_areas();
+
+            if (array_key_exists($filearea, $pluginareas)) {
+                $pluginowner = $plugin;
+                break;
+            }
+        }
+    }
+    if (!$pluginowner) {
+        foreach ($assignment->get_feedback_plugins() as $plugin) {
+            if ($plugin->is_visible()) {
+                $pluginareas = $plugin->get_file_areas();
+
+                if (array_key_exists($filearea, $pluginareas)) {
+                    $pluginowner = $plugin;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (!$pluginowner) {
+        return null;
+    }
+
+    $result = $pluginowner->get_file_info($browser, $filearea, $itemid, $filepath, $filename);
+    return $result;
+}
+
+/**
+ * Prints the complete info about a user's interaction with an assignment
+ *
+ * @param stdClass $course
+ * @param stdClass $user
+ * @param stdClass $coursemodule
+ * @param stdClass $assign the database assign record
+ *
+ * This prints the submission summary and feedback summary for this student
+ */
+function assign_user_complete($course, $user, $coursemodule, $assign) {
+    global $CFG;
+    require_once($CFG->dirroot . '/mod/assign/locallib.php');
+    $context = context_module::instance($coursemodule->id);
+
+    $assignment = new assign($context, $coursemodule, $course);
+
+    echo $assignment->view_student_summary($user, false);
+}
+
+/**
+ * Print the grade information for the assignment for this user
+ * 
+ * @param stdClass $course
+ * @param stdClass $user
+ * @param stdClass $coursemodule
+ * @param stdClass $assignment
+ */
+function assign_user_outline($course, $user, $coursemodule, $assignment) {
+    global $CFG;
+    require_once($CFG->libdir.'/gradelib.php');
+    require_once($CFG->dirroot.'/grade/grading/lib.php');
+
+    $gradinginfo = grade_get_grades($course->id,
+                                        'mod',
+                                        'assign',
+                                        $assignment->id,
+                                        $user->id);
+
+    $gradingitem = $gradinginfo->items[0];
+    $gradebookgrade = $gradingitem->grades[$user->id];
+
+    if (!$gradebookgrade) {
+        return null;
+    }
+    $result = new stdClass();
+    $result->info = get_string('outlinegrade', 'assign', $gradebookgrade->grade);
+    $result->time = $gradebookgrade->dategraded;
+
+    return $result;
+}
diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php
new file mode 100644 (file)
index 0000000..81aa234
--- /dev/null
@@ -0,0 +1,2911 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the definition for the class assignment
+ *
+ * This class provides all the functionality for the new assign module.
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Assignment submission statuses
+ */
+define('ASSIGN_SUBMISSION_STATUS_DRAFT', 'draft'); // student thinks it is a draft
+define('ASSIGN_SUBMISSION_STATUS_SUBMITTED', 'submitted'); // student thinks it is finished
+
+/**
+ * Search filters for grading page
+ */
+define('ASSIGN_FILTER_SUBMITTED', 'submitted');
+define('ASSIGN_FILTER_SINGLE_USER', 'singleuser');
+define('ASSIGN_FILTER_REQUIRE_GRADING', 'require_grading');
+
+/**
+ * File areas for assignment portfolio if enabled
+ */
+define('ASSIGN_FILEAREA_PORTFOLIO_FILES', 'portfolio_files');
+
+
+/** Include accesslib.php */
+require_once($CFG->libdir.'/accesslib.php');
+/** Include formslib.php */
+require_once($CFG->libdir.'/formslib.php');
+/** Include repository/lib.php */
+require_once($CFG->dirroot . '/repository/lib.php');
+/** Include local mod_form.php */
+require_once($CFG->dirroot.'/mod/assign/mod_form.php');
+/** Include portfoliolib.php */
+require_once($CFG->libdir . '/portfoliolib.php');
+/** gradelib.php */
+require_once($CFG->libdir.'/gradelib.php');
+/** grading lib.php */
+require_once($CFG->dirroot.'/grade/grading/lib.php');
+/** Include feedbackplugin.php */
+require_once($CFG->dirroot.'/mod/assign/feedbackplugin.php');
+/** Include submissionplugin.php */
+require_once($CFG->dirroot.'/mod/assign/submissionplugin.php');
+/** Include renderable.php */
+require_once($CFG->dirroot.'/mod/assign/renderable.php');
+/** Include gradingtable.php */
+require_once($CFG->dirroot.'/mod/assign/gradingtable.php');
+/** Include eventslib.php */
+require_once($CFG->libdir.'/eventslib.php');
+
+
+/**
+ * Standard base class for mod_assign (assignment types).
+ *
+ * @package   mod_assign
+ * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class assign {
+
+
+    /** @var stdClass the assignment record that contains the global settings for this assign instance */
+    private $instance;
+
+    /** @var context the context of the course module for this assign instance (or just the course if we are
+        creating a new one) */
+    private $context;
+
+    /** @var stdClass the course this assign instance belongs to */
+    private $course;
+
+    /** @var assign_renderer the custom renderer for this module */
+    private $output;
+
+    /** @var stdClass the course module for this assign instance */
+    private $coursemodule;
+
+    /** @var array cache for things like the coursemodule name or the scale menu - only lives for a single
+        request */
+    private $cache;
+
+    /** @var array list of the installed submission plugins */
+    private $submissionplugins;
+
+    /** @var array list of the installed feedback plugins */
+    private $feedbackplugins;
+
+    /** @var string action to be used to return to this page (without repeating any form submissions etc.) */
+    private $returnaction = 'view';
+
+    /** @var array params to be used to return to this page */
+    private $returnparams = array();
+
+    /** @var string modulename prevents excessive calls to get_string */
+    private static $modulename = '';
+
+    /** @var string modulenameplural prevents excessive calls to get_string */
+    private static $modulenameplural = '';
+
+    /**
+     * Constructor for the base assign class
+     *
+     * @param mixed $coursemodulecontext context|null the course module context (or the course context if the coursemodule has not been created yet)
+     * @param mixed $coursemodule the current course module if it was already loaded - otherwise this class will load one from the context as required
+     * @param mixed $course the current course  if it was already loaded - otherwise this class will load one from the context as required
+     */
+    public function __construct($coursemodulecontext, $coursemodule, $course) {
+        global $PAGE;
+
+        $this->context = $coursemodulecontext;
+        $this->coursemodule = $coursemodule;
+        $this->course = $course;
+        $this->cache = array(); // temporary cache only lives for a single request - used to reduce db lookups
+
+        $this->submissionplugins = $this->load_plugins('assignsubmission');
+        $this->feedbackplugins = $this->load_plugins('assignfeedback');
+        $this->output = $PAGE->get_renderer('mod_assign');
+    }
+
+    /**
+     * Set the action and parameters that can be used to return to the current page
+     *
+     * @param string $action The action for the current page
+     * @param array $params An array of name value pairs which form the parameters to return to the current page
+     * @return void
+     */
+    public function register_return_link($action, $params) {
+        $this->returnaction = $action;
+        $this->returnparams = $params;
+    }
+
+    /**
+     * Return an action that can be used to get back to the current page
+     * @return string action
+     */
+    public function get_return_action() {
+        return $this->returnaction;
+    }
+
+    /**
+     * Based on the current assignment settings should we display the intro
+     * @return bool showintro
+     */
+    private function show_intro() {
+        if ($this->get_instance()->alwaysshowdescription ||
+                time() > $this->get_instance()->allowsubmissionsfromdate) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Return a list of parameters that can be used to get back to the current page
+     * @return array params
+     */
+    public function get_return_params() {
+        return $this->returnparams;
+    }
+
+    /**
+     * Set the submitted form data
+     * @param stdClass $data The form data (instance)
+     */
+    public function set_instance(stdClass $data) {
+        $this->instance = $data;
+    }
+
+    /**
+     * Set the context
+     * @param context $context The new context
+     */
+    public function set_context(context $context) {
+        $this->context = $context;
+    }
+
+    /**
+     * Set the course data
+     * @param stdClass $course The course data
+     */
+    public function set_course(stdClass $course) {
+        $this->course = $course;
+    }
+
+    /**
+     * get list of feedback plugins installed
+     * @return array
+     */
+    public function get_feedback_plugins() {
+        return $this->feedbackplugins;
+    }
+
+    /**
+     * get list of submission plugins installed
+     * @return array
+     */
+    public function get_submission_plugins() {
+        return $this->submissionplugins;
+    }
+
+
+    /**
+     * get a specific submission plugin by its type
+     * @param string $subtype assignsubmission | assignfeedback
+     * @param string $type
+     * @return mixed assign_plugin|null
+     */
+    private function get_plugin_by_type($subtype, $type) {
+        $shortsubtype = substr($subtype, strlen('assign'));
+        $name = $shortsubtype . 'plugins';
+        $pluginlist = $this->$name;
+        foreach ($pluginlist as $plugin) {
+            if ($plugin->get_type() == $type) {
+                return $plugin;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get a feedback plugin by type
+     * @param string $type - The type of plugin e.g comments
+     * @return mixed assign_feedback_plugin|null
+     */
+    public function get_feedback_plugin_by_type($type) {
+        return $this->get_plugin_by_type('assignfeedback', $type);
+    }
+
+    /**
+     * Get a submission plugin by type
+     * @param string $type - The type of plugin e.g comments
+     * @return mixed assign_submission_plugin|null
+     */
+    public function get_submission_plugin_by_type($type) {
+        return $this->get_plugin_by_type('assignsubmission', $type);
+    }
+
+    /**
+     * Load the plugins from the sub folders under subtype
+     * @param string $subtype - either submission or feedback
+     * @return array - The sorted list of plugins
+     */
+    private function load_plugins($subtype) {
+        global $CFG;
+        $result = array();
+
+        $names = get_plugin_list($subtype);
+
+        foreach ($names as $name => $path) {
+            if (file_exists($path . '/locallib.php')) {
+                require_once($path . '/locallib.php');
+
+                $shortsubtype = substr($subtype, strlen('assign'));
+                $pluginclass = 'assign_' . $shortsubtype . '_' . $name;
+
+                $plugin = new $pluginclass($this, $name);
+
+                if ($plugin instanceof assign_plugin) {
+                    $idx = $plugin->get_sort_order();
+                    while (array_key_exists($idx, $result)) $idx +=1;
+                    $result[$idx] = $plugin;
+                }
+            }
+        }
+        ksort($result);
+        return $result;
+    }
+
+
+    /**
+     * Display the assignment, used by view.php
+     *
+     * The assignment is displayed differently depending on your role,
+     * the settings for the assignment and the status of the assignment.
+     * @param string $action The current action if any.
+     * @return void
+     */
+    public function view($action='') {
+
+        $o = '';
+        $mform = null;
+
+        // handle form submissions first
+        if ($action == 'savesubmission') {
+            $action = 'editsubmission';
+            if ($this->process_save_submission($mform)) {
+                $action = 'view';
+            }
+         } else if ($action == 'lock') {
+            $this->process_lock();
+            $action = 'grading';
+         } else if ($action == 'reverttodraft') {
+            $this->process_revert_to_draft();
+            $action = 'grading';
+         } else if ($action == 'unlock') {
+            $this->process_unlock();
+            $action = 'grading';
+         } else if ($action == 'confirmsubmit') {
+            $this->process_submit_for_grading();
+            // save and show next button
+         } else if ($action == 'batchgradingoperation') {
+            $this->process_batch_grading_operation();
+            $action = 'grading';
+         } else if ($action == 'submitgrade') {
+            if (optional_param('saveandshownext', null, PARAM_ALPHA)) {
+                //save and show next
+                $action = 'grade';
+                if ($this->process_save_grade($mform)) {
+                    $action = 'nextgrade';
+                }
+            } else if (optional_param('nosaveandprevious', null, PARAM_ALPHA)) {
+                $action = 'previousgrade';
+            } else if (optional_param('nosaveandnext', null, PARAM_ALPHA)) {
+                //show next button
+                $action = 'nextgrade';
+            } else if (optional_param('savegrade', null, PARAM_ALPHA)) {
+                //save changes button
+                $action = 'grade';
+                if ($this->process_save_grade($mform)) {
+                    $action = 'grading';
+                }
+            } else {
+                //cancel button
+                $action = 'grading';
+            }
+        }else if ($action == 'saveoptions') {
+            $this->process_save_grading_options();
+            $action = 'grading';
+        }
+
+        $returnparams = array('rownum'=>optional_param('rownum', 0, PARAM_INT));
+        $this->register_return_link($action, $returnparams);
+
+        // now show the right view page
+        if ($action == 'previousgrade') {
+            $mform = null;
+            $o .= $this->view_single_grade_page($mform, -1);
+        } else if ($action == 'nextgrade') {
+            $mform = null;
+            $o .= $this->view_single_grade_page($mform, 1);
+        } else if ($action == 'redirect') {
+            redirect(required_param('url', PARAM_TEXT));
+        } else if ($action == 'grade') {
+            $o .= $this->view_single_grade_page($mform);
+        } else if ($action == 'viewpluginassignfeedback') {
+            $o .= $this->view_plugin_content('assignfeedback');
+        } else if ($action == 'viewpluginassignsubmission') {
+            $o .= $this->view_plugin_content('assignsubmission');
+        } else if ($action == 'editsubmission') {
+            $o .= $this->view_edit_submission_page($mform);
+        } else if ($action == 'grading') {
+            $o .= $this->view_grading_page();
+        } else if ($action == 'downloadall') {
+            $o .= $this->download_submissions();
+        } else if ($action == 'submit') {
+            $o .= $this->check_submit_for_grading();
+        } else {
+            $o .= $this->view_submission_page();
+        }
+
+        return $o;
+    }
+
+
+    /**
+     * Add this instance to the database
+     *
+     * @param stdClass $formdata The data submitted from the form
+     * @param bool $callplugins This is used to skip the plugin code
+     *             when upgrading an old assignment to a new one (the plugins get called manually)
+     * @return mixed false if an error occurs or the int id of the new instance
+     */
+    public function add_instance(stdClass $formdata, $callplugins) {
+        global $DB;
+
+        $err = '';
+
+        // add the database record
+        $update = new stdClass();
+        $update->name = $formdata->name;
+        $update->timemodified = time();
+        $update->timecreated = time();
+        $update->course = $formdata->course;
+        $update->courseid = $formdata->course;
+        $update->intro = $formdata->intro;
+        $update->introformat = $formdata->introformat;
+        $update->alwaysshowdescription = $formdata->alwaysshowdescription;
+        $update->preventlatesubmissions = $formdata->preventlatesubmissions;
+        $update->submissiondrafts = $formdata->submissiondrafts;
+        $update->sendnotifications = $formdata->sendnotifications;
+        $update->duedate = $formdata->duedate;
+        $update->allowsubmissionsfromdate = $formdata->allowsubmissionsfromdate;
+        $update->grade = $formdata->grade;
+        $returnid = $DB->insert_record('assign', $update);
+        $this->instance = $DB->get_record('assign', array('id'=>$returnid), '*', MUST_EXIST);
+        // cache the course record
+        $this->course = $DB->get_record('course', array('id'=>$formdata->course), '*', MUST_EXIST);
+
+        if ($callplugins) {
+            // call save_settings hook for submission plugins
+            foreach ($this->submissionplugins as $plugin) {
+                if (!$this->update_plugin_instance($plugin, $formdata)) {
+                    print_error($plugin->get_error());
+                    return false;
+                }
+            }
+            foreach ($this->feedbackplugins as $plugin) {
+                if (!$this->update_plugin_instance($plugin, $formdata)) {
+                    print_error($plugin->get_error());
+                    return false;
+                }
+            }
+
+            // in the case of upgrades the coursemodule has not been set so we need to wait before calling these two
+            // TODO: add event to the calendar
+            $this->update_calendar($formdata->coursemodule);
+            // TODO: add the item in the gradebook
+            $this->update_gradebook(false, $formdata->coursemodule);
+
+        }
+
+        $update = new stdClass();
+        $update->id = $this->get_instance()->id;
+        $update->nosubmissions = (!$this->is_any_submission_plugin_enabled()) ? 1: 0;
+        $DB->update_record('assign', $update);
+
+        return $returnid;
+    }
+
+    /**
+     * Delete all grades from the gradebook for this assignment
+     *
+     * @return bool
+     */
+    private function delete_grades() {
+        global $CFG;
+
+        return grade_update('mod/assign', $this->get_course()->id, 'mod', 'assign', $this->get_instance()->id, 0, NULL, array('deleted'=>1)) == GRADE_UPDATE_OK;
+    }
+
+    /**
+     * Delete this instance from the database
+     *
+     * @return bool false if an error occurs
+     */
+    public function delete_instance() {
+        global $DB;
+        $result = true;
+
+        foreach ($this->submissionplugins as $plugin) {
+            if (!$plugin->delete_instance()) {
+                print_error($plugin->get_error());
+                $result = false;
+            }
+        }
+        foreach ($this->feedbackplugins as $plugin) {
+            if (!$plugin->delete_instance()) {
+                print_error($plugin->get_error());
+                $result = false;
+            }
+        }
+
+        // delete files associated with this assignment
+        $fs = get_file_storage();
+        if (! $fs->delete_area_files($this->context->id) ) {
+            $result = false;
+        }
+
+        // delete_records will throw an exception if it fails - so no need for error checking here
+
+        $DB->delete_records('assign_submission', array('assignment'=>$this->get_instance()->id));
+        $DB->delete_records('assign_grades', array('assignment'=>$this->get_instance()->id));
+        $DB->delete_records('assign_plugin_config', array('assignment'=>$this->get_instance()->id));
+
+        // delete items from the gradebook
+        if (! $this->delete_grades()) {
+            $result = false;
+        }
+
+        // delete the instance
+        $DB->delete_records('assign', array('id'=>$this->get_instance()->id));
+
+        return $result;
+    }
+
+    /**
+     * Update the settings for a single plugin
+     *
+     * @param assign_plugin $plugin The plugin to update
+     * @param stdClass $formdata The form data
+     * @return bool false if an error occurs
+     */
+    private function update_plugin_instance(assign_plugin $plugin, stdClass $formdata) {
+        if ($plugin->is_visible()) {
+            $enabledname = $plugin->get_subtype() . '_' . $plugin->get_type() . '_enabled';
+            if ($formdata->$enabledname) {
+                $plugin->enable();
+                if (!$plugin->save_settings($formdata)) {
+                    print_error($plugin->get_error());
+                    return false;
+                }
+            } else {
+                $plugin->disable();
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Update the gradebook information for this assignment
+     *
+     * @param bool $reset If true, will reset all grades in the gradbook for this assignment
+     * @param int $coursemoduleid This is required because it might not exist in the database yet
+     * @return bool
+     */
+    public function update_gradebook($reset, $coursemoduleid) {
+         global $CFG;
+        /** Include lib.php */
+        require_once($CFG->dirroot.'/mod/assign/lib.php');
+        $assign = clone $this->get_instance();
+        $assign->cmidnumber = $coursemoduleid;
+        $param = null;
+        if ($reset) {
+            $param = 'reset';
+        }
+
+        return assign_grade_item_update($assign, $param);
+    }
+
+
+    /**
+     * Update the calendar entries for this assignment
+     *
+     * @param int $coursemoduleid - Required to pass this in because it might not exist in the database yet
+     * @return bool
+     */
+    public function update_calendar($coursemoduleid) {
+        global $DB, $CFG;
+        require_once($CFG->dirroot.'/calendar/lib.php');
+
+        // special case for add_instance as the coursemodule has not been set yet.
+
+        if ($this->get_instance()->duedate) {
+            $event = new stdClass();
+
+            if ($event->id = $DB->get_field('event', 'id', array('modulename'=>'assign', 'instance'=>$this->get_instance()->id))) {
+
+                $event->name        = $this->get_instance()->name;
+
+                $event->description = format_module_intro('assign', $this->get_instance(), $coursemoduleid);
+                $event->timestart   = $this->get_instance()->duedate;
+
+                $calendarevent = calendar_event::load($event->id);
+                $calendarevent->update($event);
+            } else {
+                $event = new stdClass();
+                $event->name        = $this->get_instance()->name;
+                $event->description = format_module_intro('assign', $this->get_instance(), $coursemoduleid);
+                $event->courseid    = $this->get_instance()->course;
+                $event->groupid     = 0;
+                $event->userid      = 0;
+                $event->modulename  = 'assign';
+                $event->instance    = $this->get_instance()->id;
+                $event->eventtype   = 'due';
+                $event->timestart   = $this->get_instance()->duedate;
+                $event->timeduration = 0;
+
+                calendar_event::create($event);
+            }
+        } else {
+            $DB->delete_records('event', array('modulename'=>'assign', 'instance'=>$this->get_instance()->id));
+        }
+    }
+
+
+    /**
+     * Update this instance in the database
+     *
+     * @param stdClass $formdata - the data submitted from the form
+     * @return bool false if an error occurs
+     */
+    public function update_instance($formdata) {
+        global $DB;
+
+        $update = new stdClass();
+        $update->id = $formdata->instance;
+        $update->name = $formdata->name;
+        $update->timemodified = time();
+        $update->course = $formdata->course;
+        $update->intro = $formdata->intro;
+        $update->introformat = $formdata->introformat;
+        $update->alwaysshowdescription = $formdata->alwaysshowdescription;
+        $update->preventlatesubmissions = $formdata->preventlatesubmissions;
+        $update->submissiondrafts = $formdata->submissiondrafts;
+        $update->sendnotifications = $formdata->sendnotifications;
+        $update->duedate = $formdata->duedate;
+        $update->allowsubmissionsfromdate = $formdata->allowsubmissionsfromdate;
+        $update->grade = $formdata->grade;
+
+        $result = $DB->update_record('assign', $update);
+        $this->instance = $DB->get_record('assign', array('id'=>$update->id), '*', MUST_EXIST);
+
+        // load the assignment so the plugins have access to it
+
+        // call save_settings hook for submission plugins
+        foreach ($this->submissionplugins as $plugin) {
+            if (!$this->update_plugin_instance($plugin, $formdata)) {
+                print_error($plugin->get_error());
+                return false;
+            }
+        }
+        foreach ($this->feedbackplugins as $plugin) {
+            if (!$this->update_plugin_instance($plugin, $formdata)) {
+                print_error($plugin->get_error());
+                return false;
+            }
+        }
+
+
+        // update the database record
+
+
+        // update all the calendar events
+        $this->update_calendar($this->get_course_module()->id);
+
+        $this->update_gradebook(false, $this->get_course_module()->id);
+
+        $update = new stdClass();
+        $update->id = $this->get_instance()->id;
+        $update->nosubmissions = (!$this->is_any_submission_plugin_enabled()) ? 1: 0;
+        $DB->update_record('assign', $update);
+
+
+
+
+
+        return $result;
+    }
+
+    /**
+     * add elements in grading plugin form
+     *
+     * @param mixed $grade stdClass|null
+     * @param MoodleQuickForm $mform
+     * @param stdClass $data
+     * @return void
+     */
+    private function add_plugin_grade_elements($grade, MoodleQuickForm $mform, stdClass $data) {
+        foreach ($this->feedbackplugins as $plugin) {
+            if ($plugin->is_enabled() && $plugin->is_visible()) {
+                $mform->addElement('header', 'header_' . $plugin->get_type(), $plugin->get_name());
+                if (!$plugin->get_form_elements($grade, $mform, $data)) {
+                    $mform->removeElement('header_' . $plugin->get_type());
+                }
+            }
+        }
+    }
+
+
+
+    /**
+     * Add one plugins settings to edit plugin form
+     *
+     * @param assign_plugin $plugin The plugin to add the settings from
+     * @param MoodleQuickForm $mform The form to add the configuration settings to. This form is modified directly (not returned)
+     * @return void
+     */
+    private function add_plugin_settings(assign_plugin $plugin, MoodleQuickForm $mform) {
+        global $CFG;
+        if ($plugin->is_visible()) {
+            // enabled
+            //tied disableIf rule to this select element
+            $mform->addElement('selectyesno', $plugin->get_subtype() . '_' . $plugin->get_type() . '_enabled', $plugin->get_name());
+            $mform->addHelpButton($plugin->get_subtype() . '_' . $plugin->get_type() . '_enabled', 'enabled', $plugin->get_subtype() . '_' . $plugin->get_type());
+
+            $setting = $plugin->get_subtype() . '_' . $plugin->get_type() . '_default';
+
+            $default = $CFG->$setting;
+            if ($plugin->get_config('enabled') !== false) {
+                $default = $plugin->is_enabled();
+            }
+            $mform->setDefault($plugin->get_subtype() . '_' . $plugin->get_type() . '_enabled', $default);
+
+            $plugin->get_settings($mform);
+
+        }
+
+    }
+
+
+    /**
+     * Add settings to edit plugin form
+     *
+     * @param MoodleQuickForm $mform The form to add the configuration settings to. This form is modified directly (not returned)
+     * @return void
+     */
+    public function add_all_plugin_settings(MoodleQuickForm $mform) {
+        $mform->addElement('header', 'general', get_string('submissionsettings', 'assign'));
+
+        foreach ($this->submissionplugins as $plugin) {
+            $this->add_plugin_settings($plugin, $mform);
+
+        }
+        $mform->addElement('header', 'general', get_string('feedbacksettings', 'assign'));
+        foreach ($this->feedbackplugins as $plugin) {
+            $this->add_plugin_settings($plugin, $mform);
+        }
+    }
+
+    /**
+     * Allow each plugin an opportunity to update the defaultvalues
+     * passed in to the settings form (needed to set up draft areas for
+     * editor and filemanager elements)
+     * @param array $defaultvalues
+     */
+    public function plugin_data_preprocessing(&$defaultvalues) {
+        foreach ($this->submissionplugins as $plugin) {
+            if ($plugin->is_visible()) {
+                $plugin->data_preprocessing($defaultvalues);
+            }
+        }
+        foreach ($this->feedbackplugins as $plugin) {
+            if ($plugin->is_visible()) {
+                $plugin->data_preprocessing($defaultvalues);
+            }
+        }
+    }
+
+    /**
+     * Get the name of the current module.
+     *
+     * @return string the module name (Assignment)
+     */
+    protected function get_module_name() {
+        if (isset(self::$modulename)) {
+            return self::$modulename;
+        }
+        self::$modulename = get_string('modulename', 'assign');
+        return self::$modulename;
+    }
+
+    /**
+     * Get the plural name of the current module.
+     *
+     * @return string the module name plural (Assignments)
+     */
+    protected function get_module_name_plural() {
+        if (isset(self::$modulenameplural)) {
+            return self::$modulenameplural;
+        }
+        self::$modulenameplural = get_string('modulenameplural', 'assign');
+        return self::$modulenameplural;
+    }
+
+    /**
+     * Has this assignment been constructed from an instance?
+     *
+     * @return bool
+     */
+    public function has_instance() {
+        return $this->instance || $this->get_course_module();
+    }
+
+    /**
+     * Get the settings for the current instance of this assignment
+     *
+     * @return stdClass The settings
+     */
+    public function get_instance() {
+        global $DB;
+        if ($this->instance) {
+            return $this->instance;
+        }
+        if ($this->get_course_module()) {
+            $this->instance = $DB->get_record('assign', array('id' => $this->get_course_module()->instance), '*', MUST_EXIST);
+        }
+        if (!$this->instance) {
+            throw new coding_exception('Improper use of the assignment class. Cannot load the assignment record.');
+        }
+        return $this->instance;
+    }
+
+    /**
+     * Get the context of the current course
+     * @return mixed context|null The course context
+     */
+    public function get_course_context() {
+        if (!$this->context && !$this->course) {
+            throw new coding_exception('Improper use of the assignment class. Cannot load the course context.');
+        }
+        if ($this->context) {
+            return $this->context->get_course_context();
+        } else {
+            return context_course::instance($this->course->id);
+        }
+    }
+
+
+    /**
+     * Get the current course module
+     *
+     * @return mixed stdClass|null The course module
+     */
+    public function get_course_module() {
+        if ($this->coursemodule) {
+            return $this->coursemodule;
+        }
+        if (!$this->context) {
+            return null;
+        }
+
+        if ($this->context->contextlevel == CONTEXT_MODULE) {
+            $this->coursemodule = get_coursemodule_from_id('assign', $this->context->instanceid, 0, false, MUST_EXIST);
+            return $this->coursemodule;
+        }
+        return null;
+    }
+
+    /**
+     * Get context module
+     *
+     * @return context
+     */
+    public function get_context() {
+        return $this->context;
+    }
+
+    /**
+     * Get the current course
+     * @return mixed stdClass|null The course
+     */
+    public function get_course() {
+        global $DB;
+        if ($this->course) {
+            return $this->course;
+        }
+
+        if (!$this->context) {
+            return null;
+        }
+        $this->course = $DB->get_record('course', array('id' => $this->get_course_context()->instanceid), '*', MUST_EXIST);
+        return $this->course;
+    }
+
+    /**
+     * Return a grade in user-friendly form, whether it's a scale or not
+     *
+     * @param mixed $grade int|null 
+     * @return string User-friendly representation of grade
+     */
+    public function display_grade($grade) {
+        global $DB;
+
+        static $scalegrades = array();
+
+
+
+        if ($this->get_instance()->grade >= 0) {    // Normal number
+            if ($grade == -1 || $grade === null) {
+                return '-';
+            } else {
+                return format_float(($grade),2) .'&nbsp;/&nbsp;'. format_float($this->get_instance()->grade,2);
+            }
+
+        } else {                                // Scale
+            if (empty($this->cache['scale'])) {
+                if ($scale = $DB->get_record('scale', array('id'=>-($this->get_instance()->grade)))) {
+                    $this->cache['scale'] = make_menu_from_list($scale->scale);
+                } else {
+                    return '-';
+                }
+            }
+            $scaleid = (int)$grade;
+            if (isset($this->cache['scale'][$scaleid])) {
+                return $this->cache['scale'][$scaleid];
+            }
+            return '-';
+        }
+    }
+
+    /**
+     * Load a list of users enrolled in the current course with the specified permission and group (0 for no group)
+     *
+     * @param int $currentgroup
+     * @param bool $idsonly
+     * @return array List of user records
+     */
+    public function list_participants($currentgroup, $idsonly) {
+        if ($idsonly) {
+            return get_enrolled_users($this->context, "mod/assign:submit", $currentgroup, 'u.id');
+        } else {
+            return get_enrolled_users($this->context, "mod/assign:submit", $currentgroup);
+        }
+    }
+
+    /**
+     * Load a count of users enrolled in the current course with the specified permission and group (0 for no group)
+     *
+     * @param int $currentgroup
+     * @return int number of matching users
+     */
+    public function count_participants($currentgroup) {
+        return count_enrolled_users($this->context, "mod/assign:submit", $currentgroup);
+    }
+
+    /**
+     * Load a count of users enrolled in the current course with the specified permission and group (optional)
+     *
+     * @param string $status The submission status - should match one of the constants
+     * @return int number of matching submissions
+     */
+    public function count_submissions_with_status($status) {
+        global $DB;
+        return $DB->count_records_sql("SELECT COUNT('x')
+                                     FROM {assign_submission}
+                                    WHERE assignment = ? AND
+                                          status = ?", array($this->get_course_module()->instance, $status));
+    }
+
+    /**
+     * Utility function to get the userid for every row in the grading table
+     * so the order can be frozen while we iterate it
+     *
+     * @return array An array of userids
+     */
+    private function get_grading_userid_list(){
+        $filter = get_user_preferences('assign_filter', '');
+        $table = new assign_grading_table($this, 0, $filter);
+
+        $useridlist = $table->get_column_data('userid');
+
+        return $useridlist;
+    }
+
+
+    /**
+     * Utility function get the userid based on the row number of the grading table.
+     * This takes into account any active filters on the table.
+     *
+     * @param int $num The row number of the user
+     * @param bool $last This is set to true if this is the last user in the table
+     * @return mixed The user id of the matching user or false if there was an error
+     */
+    private function get_userid_for_row($num, $last){
+        if (!array_key_exists('userid_for_row', $this->cache)) {
+            $this->cache['userid_for_row'] = array();
+        }
+        if (array_key_exists($num, $this->cache['userid_for_row'])) {
+            list($userid, $last) = $this->cache['userid_for_row'][$num];
+            return $userid;
+        }
+
+        $filter = get_user_preferences('assign_filter', '');
+        $table = new assign_grading_table($this, 0, $filter);
+
+        $userid = $table->get_cell_data($num, 'userid', $last);
+
+        $this->cache['userid_for_row'][$num] = array($userid, $last);
+        return $userid;
+    }
+
+    /**
+     * Return all assignment submissions by ENROLLED students (even empty)
+     *
+     * @param string $sort optional field names for the ORDER BY in the sql query
+     * @param string $dir optional specifying the sort direction, defaults to DESC
+     * @return array The submission objects indexed by id
+     */
+    private function get_all_submissions( $sort="", $dir="DESC") {
+        global $CFG, $DB;
+
+        if ($sort == "lastname" or $sort == "firstname") {
+            $sort = "u.$sort $dir";
+        } else if (empty($sort)) {
+            $sort = "a.timemodified DESC";
+        } else {
+            $sort = "a.$sort $dir";
+        }
+
+        return $DB->get_records_sql("SELECT a.*
+                                       FROM {assign_submission} a, {user} u
+                                      WHERE u.id = a.userid
+                                            AND a.assignment = ?
+                                   ORDER BY $sort", array($this->get_instance()->id));
+
+    }
+
+    /**
+     * Generate zip file from array of given files
+     *
+     * @param array $filesforzipping - array of files to pass into archive_to_pathname - this array is indexed by the final file name and each element in the array is an instance of a stored_file object
+     * @return path of temp file - note this returned file does not have a .zip extension - it is a temp file.
+     */
+     private function pack_files($filesforzipping) {
+         global $CFG;
+         //create path for new zip file.
+         $tempzip = tempnam($CFG->tempdir.'/', 'assignment_');
+         //zip files
+         $zipper = new zip_packer();
+         if ($zipper->archive_to_pathname($filesforzipping, $tempzip)) {
+             return $tempzip;
+         }
+         return false;
+    }
+
+
+    /**
+     *  Cron function to be run periodically according to the moodle cron
+     *  Finds all assignment notifications that have yet to be mailed out, and mails them
+     *
+     * @return bool
+     */
+    static function cron() {
+        global $CFG, $USER, $DB;
+
+
+        return true;
+    }
+
+    /**
+     * Update a grade in the grade table for the assignment and in the gradebook
+     *
+     * @param stdClass $grade a grade record keyed on id
+     * @return bool true for success
+     */
+    private function update_grade($grade) {
+        global $DB;
+
+        $grade->timemodified = time();
+
+        if ($grade->grade && $grade->grade != -1) {
+            if ($this->get_instance()->grade > 0) {
+                if (!is_numeric($grade->grade)) {
+                    return false;
+                } else if ($grade->grade > $this->get_instance()->grade) {
+                    return false;
+                } else if ($grade->grade < 0) {
+                    return false;
+                }
+            } else {
+                // this is a scale
+                if ($scale = $DB->get_record('scale', array('id' => -($this->get_instance()->grade)))) {
+                    $scaleoptions = make_menu_from_list($scale->scale);
+                    if (!array_key_exists((int) $grade->grade, $scaleoptions)) {
+                        return false;
+                    }
+                }
+            }
+        }
+
+        $result = $DB->update_record('assign_grades', $grade);
+        if ($result) {
+            $this->gradebook_item_update(null, $grade);
+        }
+        return $result;
+    }
+
+    /**
+     * display the submission that is used by a plugin
+     * Uses url parameters 'sid', 'gid' and 'plugin'
+     * @param string $pluginsubtype
+     * @return string
+     */
+    private function view_plugin_content($pluginsubtype) {
+        global $USER;
+
+        $o = '';
+
+        $submissionid = optional_param('sid', 0, PARAM_INT);
+        $gradeid = optional_param('gid', 0, PARAM_INT);
+        $plugintype = required_param('plugin', PARAM_TEXT);
+        $item = null;
+        if ($pluginsubtype == 'assignsubmission') {
+            $plugin = $this->get_submission_plugin_by_type($plugintype);
+            if ($submissionid <= 0) {
+                throw new coding_exception('Submission id should not be 0');
+            }
+            $item = $this->get_submission($submissionid);
+
+            // permissions
+            if ($item->userid != $USER->id) {
+                require_capability('mod/assign:grade', $this->context);
+            }
+            $o .= $this->output->render(new assign_header($this->get_instance(),
+                                                              $this->get_context(),
+                                                              $this->show_intro(),
+                                                              $this->get_course_module()->id,
+                                                              $plugin->get_name()));
+            $o .= $this->output->render(new assign_submission_plugin_submission($plugin,
+                                                              $item,
+                                                              assign_submission_plugin_submission::FULL,
+                                                              $this->get_course_module()->id,
+                                                              $this->get_return_action(),
+                                                              $this->get_return_params()));
+
+            $this->add_to_log('view submission', get_string('viewsubmissionforuser', 'assign', $item->userid));
+        } else {
+            $plugin = $this->get_feedback_plugin_by_type($plugintype);
+            if ($gradeid <= 0) {
+                throw new coding_exception('Grade id should not be 0');
+            }
+            $item = $this->get_grade($gradeid);
+            // permissions
+            if ($item->userid != $USER->id) {
+                require_capability('mod/assign:grade', $this->context);
+            }
+            $o .= $this->output->render(new assign_header($this->get_instance(),
+                                                              $this->get_context(),
+                                                              $this->show_intro(),
+                                                              $this->get_course_module()->id,
+                                                              $plugin->get_name()));
+            $o .= $this->output->render(new assign_feedback_plugin_feedback($plugin,
+                                                              $item,
+                                                              assign_feedback_plugin_feedback::FULL,
+                                                              $this->get_course_module()->id,
+                                                              $this->get_return_action(),
+                                                              $this->get_return_params()));
+            $this->add_to_log('view feedback', get_string('viewfeedbackforuser', 'assign', $item->userid));
+        }
+
+
+        $o .= $this->view_return_links();
+
+        $o .= $this->view_footer();
+        return $o;
+    }
+
+    /**
+     * render the content in editor that is often used by plugin
+     *
+     * @param string $filearea
+     * @param int  $submissionid
+     * @param string $plugintype
+     * @param string $editor
+     * @param string $component
+     * @return string
+     */
+    public function render_editor_content($filearea, $submissionid, $plugintype, $editor, $component) {
+        global $CFG;
+
+        $result = '';
+
+        $plugin = $this->get_submission_plugin_by_type($plugintype);
+
+        $text = $plugin->get_editor_text($editor, $submissionid);
+        $format = $plugin->get_editor_format($editor, $submissionid);
+
+        $finaltext = file_rewrite_pluginfile_urls($text, 'pluginfile.php', $this->get_context()->id, $component, $filearea, $submissionid);
+        $result .= format_text($finaltext, $format, array('overflowdiv' => true, 'context' => $this->get_context()));
+
+
+
+        if ($CFG->enableportfolios) {
+            require_once($CFG->libdir . '/portfoliolib.php');
+
+            $button = new portfolio_add_button();
+            $button->set_callback_options('assign_portfolio_caller', array('cmid' => $this->get_course_module()->id, 'sid' => $submissionid, 'plugin' => $plugintype, 'editor' => $editor, 'area'=>$filearea), '/mod/assign/portfolio_callback.php');
+            $fs = get_file_storage();
+
+            if ($files = $fs->get_area_files($this->context->id, $component,$filearea, $submissionid, "timemodified", false)) {
+                $button->set_formats(PORTFOLIO_FORMAT_RICHHTML);
+            } else {
+                $button->set_formats(PORTFOLIO_FORMAT_PLAINHTML);
+            }
+            $result .= $button->to_html();
+        }
+        return $result;
+    }
+
+
+    /**
+     * Display the page footer
+     *
+     * @return None
+     */
+    private function view_footer() {
+        return $this->output->render_footer();
+    }
+
+    /**
+     * Does this user have grade permission for this assignment
+     *
+     * @return bool
+     */
+    private function can_grade() {
+        // Permissions check
+        if (!has_capability('mod/assign:grade', $this->context)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Download a zip file of all assignment submissions
+     *
+     * @return void
+     */
+    private function download_submissions() {
+        global $CFG,$DB;
+
+        // more efficient to load this here
+        require_once($CFG->libdir.'/filelib.php');
+
+        // load all submissions
+        $submissions = $this->get_all_submissions('','');
+
+        if (empty($submissions)) {
+            print_error('errornosubmissions', 'assign');
+            return;
+        }
+
+        // build a list of files to zip
+        $filesforzipping = array();
+        $fs = get_file_storage();
+
+        $groupmode = groups_get_activity_groupmode($this->get_course_module());
+        $groupid = 0;   // All users
+        $groupname = '';
+        if ($groupmode) {
+            $groupid = groups_get_activity_group($this->get_course_module(), true);
+            $groupname = groups_get_group_name($groupid).'-';
+        }
+
+        // construct the zip file name
+        $filename = str_replace(' ', '_', clean_filename($this->get_course()->shortname.'-'.$this->get_instance()->name.'-'.$groupname.$this->get_course_module()->id.".zip")); //name of new zip file.
+
+        // get all the files for each submission
+        foreach ($submissions as $submission) {
+            $userid = $submission->userid; //get userid
+            if ((groups_is_member($groupid,$userid) or !$groupmode or !$groupid)) {
+                // get the plugins to add their own files to the zip
+
+                $user = $DB->get_record("user", array("id"=>$userid),'id,username,firstname,lastname', MUST_EXIST);
+
+                $prefix = clean_filename(fullname($user) . "_" .$userid . "_");
+
+                foreach ($this->submissionplugins as $plugin) {
+                    if ($plugin->is_enabled() && $plugin->is_visible()) {
+                        $pluginfiles = $plugin->get_files($submission);
+
+
+                        foreach ($pluginfiles as $zipfilename => $file) {
+                            $filesforzipping[$prefix . $zipfilename] = $file;
+                        }
+                    }
+                }
+
+            }
+        } // end of foreach loop
+        if ($zipfile = $this->pack_files($filesforzipping)) {
+            $this->add_to_log('download all submissions', get_string('downloadall', 'assign'));
+            send_temp_file($zipfile, $filename); //send file and delete after sending.
+        }
+    }
+
+    /**
+     * Util function to add a message to the log
+     *
+     * @param string $action The current action
+     * @param string $info A detailed description of the change. But no more than 255 characters.
+     * @param string $url The url to the assign module instance.
+     * @return void
+     */
+    public function add_to_log($action = '', $info = '', $url='') {
+        global $USER;
+
+        $fullurl = 'view.php?id=' . $this->get_course_module()->id;
+        if ($url != '') {
+            $fullurl .= '&' . $url;
+        }
+
+        add_to_log($this->get_course()->id, 'assign', $action, $fullurl, $info, $this->get_course_module()->id, $USER->id);
+    }
+
+    /**
+     * Load the submission object for a particular user, optionally creating it if required
+     *
+     * @param int $userid The id of the user whose submission we want or 0 in which case USER->id is used
+     * @param bool $create optional Defaults to false. If set to true a new submission object will be created in the database
+     * @return stdClass The submission
+     */
+    private function get_user_submission($userid, $create) {
+        global $DB, $USER;
+
+        if (!$userid) {
+            $userid = $USER->id;
+        }
+        // if the userid is not null then use userid
+        $submission = $DB->get_record('assign_submission', array('assignment'=>$this->get_instance()->id, 'userid'=>$userid));
+
+        if ($submission) {
+            return $submission;
+        }
+        if ($create) {
+            $submission = new stdClass();
+            $submission->assignment   = $this->get_instance()->id;
+            $submission->userid       = $userid;
+            $submission->timecreated = time();
+            $submission->timemodified = $submission->timecreated;
+
+            if ($this->get_instance()->submissiondrafts) {
+                $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
+            } else {
+                $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+            }
+            $sid = $DB->insert_record('assign_submission', $submission);
+            $submission->id = $sid;
+            return $submission;
+        }
+        return false;
+    }
+
+    /**
+     * Load the submission object from it's id
+     *
+     * @param int $submissionid The id of the submission we want
+     * @return stdClass The submission
+     */
+    private function get_submission($submissionid) {
+        global $DB;
+
+        return $DB->get_record('assign_submission', array('assignment'=>$this->get_instance()->id, 'id'=>$submissionid), '*', MUST_EXIST);
+    }
+
+    /**
+     * This will retrieve a grade object from the db, optionally creating it if required
+     *
+     * @param int $userid The user we are grading
+     * @param bool $create If true the grade will be created if it does not exist
+     * @return stdClass The grade record
+     */
+    private function get_user_grade($userid, $create) {
+        global $DB, $USER;
+
+        if (!$userid) {
+            $userid = $USER->id;
+        }
+
+        // if the userid is not null then use userid
+        $grade = $DB->get_record('assign_grades', array('assignment'=>$this->get_instance()->id, 'userid'=>$userid));
+
+        if ($grade) {
+            return $grade;
+        }
+        if ($create) {
+            $grade = new stdClass();
+            $grade->assignment   = $this->get_instance()->id;
+            $grade->userid       = $userid;
+            $grade->timecreated = time();
+            $grade->timemodified = $grade->timecreated;
+            $grade->locked = 0;
+            $grade->grade = -1;
+            $grade->grader = $USER->id;
+            $gid = $DB->insert_record('assign_grades', $grade);
+            $grade->id = $gid;
+            return $grade;
+        }
+        return false;
+    }
+
+    /**
+     * This will retrieve a grade object from the db
+     *
+     * @param int $gradeid The id of the grade
+     * @return stdClass The grade record