Setting some default parameters when adding an lti instance
authorChris Scribner <scriby@gmail.com>
Thu, 1 Sep 2011 18:17:59 +0000 (14:17 -0400)
committerChris Scribner <scriby@gmail.com>
Mon, 7 Nov 2011 01:41:49 +0000 (20:41 -0500)
mod/lti/lib.php

index abb51dd..c1ee7c6 100644 (file)
-<?php\r
-// This file is part of BasicLTI4Moodle\r
-//\r
-// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)\r
-// consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web\r
-// based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI\r
-// specification is part of the IMS standard Common Cartridge 1.1 Sakai and other main LMS\r
-// are already supporting or going to support BasicLTI. This project Implements the consumer\r
-// for Moodle. Moodle is a Free Open source Learning Management System by Martin Dougiamas.\r
-// BasicLTI4Moodle is a project iniciated and leaded by Ludo(Marc Alier) and Jordi Piguillem\r
-// at the GESSI research group at UPC.\r
-// SimpleLTI consumer for Moodle is an implementation of the early specification of LTI\r
-// by Charles Severance (Dr Chuck) htp://dr-chuck.com , developed by Jordi Piguillem in a\r
-// Google Summer of Code 2008 project co-mentored by Charles Severance and Marc Alier.\r
-//\r
-// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis\r
-// of the Universitat Politecnica de Catalunya http://www.upc.edu\r
-// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu\r
-//\r
-// Moodle is free software: you can redistribute it and/or modify\r
-// it under the terms of the GNU General Public License as published by\r
-// the Free Software Foundation, either version 3 of the License, or\r
-// (at your option) any later version.\r
-//\r
-// Moodle is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-// GNU General Public License for more details.\r
-//\r
-// You should have received a copy of the GNU General Public License\r
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\r
-\r
-/**\r
- * This file contains a library of functions and constants for the\r
- * BasicLTI module\r
- *\r
- * @package lti\r
- * @copyright 2009 Marc Alier, Jordi Piguillem, Nikolas Galanis\r
- *  marc.alier@upc.edu\r
- * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu\r
- *\r
- * @author Marc Alier\r
- * @author Jordi Piguillem\r
- * @author Nikolas Galanis\r
- *\r
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\r
- */\r
-\r
-defined('MOODLE_INTERNAL') || die;\r
-\r
-require_once($CFG->dirroot.'/mod/lti/locallib.php');\r
-\r
-/**\r
- * List of features supported in URL module\r
- * @param string $feature FEATURE_xx constant for requested feature\r
- * @return mixed True if module supports feature, false if not, null if doesn't know\r
- */\r
-function lti_supports($feature) {\r
-    switch($feature) {\r
-        case FEATURE_GROUPS:                  return false;\r
-        case FEATURE_GROUPINGS:               return false;\r
-        case FEATURE_GROUPMEMBERSONLY:        return true;\r
-        case FEATURE_MOD_INTRO:               return true;\r
-        case FEATURE_COMPLETION_TRACKS_VIEWS: return true;\r
-        case FEATURE_GRADE_HAS_GRADE:         return true;\r
-        case FEATURE_GRADE_OUTCOMES:          return true;\r
-        case FEATURE_BACKUP_MOODLE2:          return true;\r
-\r
-        default: return null;\r
-    }\r
-}\r
-\r
-/**\r
- * Given an object containing all the necessary data,\r
- * (defined by the form in mod.html) this function\r
- * will create a new instance and return the id number\r
- * of the new instance.\r
- *\r
- * @param object $instance An object from the form in mod.html\r
- * @return int The id of the newly inserted basiclti record\r
- **/\r
-function lti_add_instance($formdata) {\r
-    global $DB;\r
-    $formdata->timecreated = time();\r
-    $formdata->timemodified = $formdata->timecreated;\r
-    //$basiclti->placementsecret = uniqid('', true);\r
-    //$basiclti->timeplacementsecret = time();\r
-\r
-    $id = $DB->insert_record("lti", $formdata);\r
-\r
-    if ($formdata->instructorchoiceacceptgrades == 1) {\r
-        $basiclti = $DB->get_record('lti', array('id'=>$id));\r
-        $basiclti->cmidnumber = $formdata->cmidnumber;\r
-        \r
-        lti_grade_item_update($basiclti);\r
-    }\r
-\r
-    return $id;\r
-}\r
-\r
-/**\r
- * Given an object containing all the necessary data,\r
- * (defined by the form in mod.html) this function\r
- * will update an existing instance with new data.\r
- *\r
- * @param object $instance An object from the form in mod.html\r
- * @return boolean Success/Fail\r
- **/\r
-function lti_update_instance($formdata) {\r
-    global $DB;\r
-\r
-    $formdata->timemodified = time();\r
-    $formdata->id = $formdata->instance;\r
-\r
-    if(!isset($formdata->showtitle)){\r
-        $formdata->showtitle = 0;\r
-    }\r
-    \r
-    if(!isset($formdata->showdescription)){\r
-        $formdata->showdescription = 0;\r
-    }\r
-    \r
-    if ($formdata->instructorchoiceacceptgrades == 1) {\r
-        $basicltirec = $DB->get_record("lti", array("id" => $formdata->id));\r
-        $basicltirec->cmidnumber = $formdata->cmidnumber;\r
-        \r
-        lti_grade_item_update($basicltirec);\r
-    } else {\r
-        lti_grade_item_delete($formdata);\r
-    }\r
-\r
-    return $DB->update_record("lti", $formdata);\r
-}\r
-\r
-/**\r
- * Given an ID of an instance of this module,\r
- * this function will permanently delete the instance\r
- * and any data that depends on it.\r
- *\r
- * @param int $id Id of the module instance\r
- * @return boolean Success/Failure\r
- **/\r
-function lti_delete_instance($id) {\r
-    global $DB;\r
-\r
-    if (! $basiclti = $DB->get_record("lti", array("id" => $id))) {\r
-        return false;\r
-    }\r
-\r
-    $result = true;\r
-\r
-    # Delete any dependent records here #\r
-    lti_grade_item_delete($basiclti);\r
-\r
-    return $DB->delete_records("lti", array("id" => $basiclti->id));\r
-}\r
-\r
-/**\r
- * Return a small object with summary information about what a\r
- * user has done with a given particular instance of this module\r
- * Used for user activity reports.\r
- * $return->time = the time they did it\r
- * $return->info = a short text description\r
- *\r
- * @return null\r
- * @TODO: implement this moodle function (if needed)\r
- **/\r
-function lti_user_outline($course, $user, $mod, $basiclti) {\r
-    return $return;\r
-}\r
-\r
-/**\r
- * Print a detailed representation of what a user has done with\r
- * a given particular instance of this module, for user activity reports.\r
- *\r
- * @return boolean\r
- * @TODO: implement this moodle function (if needed)\r
- **/\r
-function lti_user_complete($course, $user, $mod, $basiclti) {\r
-    return true;\r
-}\r
-\r
-/**\r
- * Given a course and a time, this module should find recent activity\r
- * that has occurred in basiclti activities and print it out.\r
- * Return true if there was output, or false is there was none.\r
- *\r
- * @uses $CFG\r
- * @return boolean\r
- * @TODO: implement this moodle function\r
- **/\r
-function lti_print_recent_activity($course, $isteacher, $timestart) {\r
-    return false;  //  True if anything was printed, otherwise false\r
-}\r
-\r
-/**\r
- * Function to be run periodically according to the moodle cron\r
- * This function searches for things that need to be done, such\r
- * as sending out mail, toggling flags etc ...\r
- *\r
- * @uses $CFG\r
- * @return boolean\r
- **/\r
-function lti_cron () {\r
-    return true;\r
-}\r
-\r
-/**\r
- * Must return an array of grades for a given instance of this module,\r
- * indexed by user.  It also returns a maximum allowed grade.\r
- *\r
- * Example:\r
- *    $return->grades = array of grades;\r
- *    $return->maxgrade = maximum allowed grade;\r
- *\r
- *    return $return;\r
- *\r
- * @param int $basicltiid ID of an instance of this module\r
- * @return mixed Null or object with an array of grades and with the maximum grade\r
- *\r
- * @TODO: implement this moodle function (if needed)\r
- **/\r
-function lti_grades($basicltiid) {\r
-    return null;\r
-}\r
-\r
-/**\r
- * Must return an array of user records (all data) who are participants\r
- * for a given instance of basiclti. Must include every user involved\r
- * in the instance, independient of his role (student, teacher, admin...)\r
- * See other modules as example.\r
- *\r
- * @param int $basicltiid ID of an instance of this module\r
- * @return mixed boolean/array of students\r
- *\r
- * @TODO: implement this moodle function\r
- **/\r
-function lti_get_participants($basicltiid) {\r
-    return false;\r
-}\r
-\r
-/**\r
- * This function returns if a scale is being used by one basiclti\r
- * it it has support for grading and scales. Commented code should be\r
- * modified if necessary. See forum, glossary or journal modules\r
- * as reference.\r
- *\r
- * @param int $basicltiid ID of an instance of this module\r
- * @return mixed\r
- *\r
- * @TODO: implement this moodle function (if needed)\r
- **/\r
-function lti_scale_used ($basicltiid, $scaleid) {\r
-    $return = false;\r
-\r
-    //$rec = get_record("basiclti","id","$basicltiid","scale","-$scaleid");\r
-    //\r
-    //if (!empty($rec)  && !empty($scaleid)) {\r
-    //    $return = true;\r
-    //}\r
-\r
-    return $return;\r
-}\r
-\r
-/**\r
- * Checks if scale is being used by any instance of basiclti.\r
- * This function was added in 1.9\r
- *\r
- * This is used to find out if scale used anywhere\r
- * @param $scaleid int\r
- * @return boolean True if the scale is used by any basiclti\r
- *\r
- */\r
-function lti_scale_used_anywhere($scaleid) {\r
-    global $DB;\r
-\r
-    if ($scaleid and $DB->record_exists('lti', array('grade' => -$scaleid))) {\r
-        return true;\r
-    } else {\r
-        return false;\r
-    }\r
-}\r
-\r
-/**\r
- * Execute post-install custom actions for the module\r
- * This function was added in 1.9\r
- *\r
- * @return boolean true if success, false on error\r
- */\r
-function lti_install() {\r
-     return true;\r
-}\r
-\r
-/**\r
- * Execute post-uninstall custom actions for the module\r
- * This function was added in 1.9\r
- *\r
- * @return boolean true if success, false on error\r
- */\r
-function lti_uninstall() {\r
-    return true;\r
-}\r
-\r
-/**\r
- * Returns available Basic LTI types\r
- *\r
- * @return array of basicLTI types\r
- */\r
-function lti_get_lti_types() {\r
-    global $DB;\r
-\r
-    return $DB->get_records('lti_types');\r
-}\r
-\r
-/**\r
- * Returns Basic LTI types configuration\r
- *\r
- * @return array of basicLTI types\r
- */\r
-/*function lti_get_types() {\r
-    $types = array();\r
-\r
-    $basicltitypes = lti_get_lti_types();\r
-    if (!empty($basicltitypes)) {\r
-        foreach ($basicltitypes as $basicltitype) {\r
-            $ltitypesconfig = lti_get_type_config($basicltitype->id);\r
-\r
-            $modclass = MOD_CLASS_ACTIVITY;\r
-            if (isset($ltitypesconfig['module_class_type'])) {\r
-                if ($ltitypesconfig['module_class_type']=='1') {\r
-                    $modclass = MOD_CLASS_RESOURCE;\r
-                }\r
-            }\r
-\r
-            $type = new object();\r
-            $type->modclass = $modclass;\r
-            $type->type = 'lti&amp;type='.urlencode($basicltitype->rawname);\r
-            $type->typestr = $basicltitype->name;\r
-            $types[] = $type;\r
-        }\r
-    }\r
-\r
-    return $types;\r
-}*/\r
-\r
-//////////////////////////////////////////////////////////////////////////////////////\r
-/// Any other basiclti functions go here.  Each of them must have a name that\r
-/// starts with basiclti_\r
-/// Remember (see note in first lines) that, if this section grows, it's HIGHLY\r
-/// recommended to move all funcions below to a new "localib.php" file.\r
-\r
-///**\r
-// *\r
-// */\r
-//function process_outcomes($userid, $course, $basiclti) {\r
-//    global $CFG, $USER;\r
-//\r
-//    if (empty($CFG->enableoutcomes)) {\r
-//        return;\r
-//    }\r
-//\r
-//    require_once($CFG->libdir.'/gradelib.php');\r
-//\r
-//    if (!$formdata = data_submitted() or !confirm_sesskey()) {\r
-//        return;\r
-//    }\r
-//\r
-//    $data = array();\r
-//    $grading_info = grade_get_grades($course->id, 'mod', 'basiclti', $basiclti->id, $userid);\r
-//\r
-//    if (!empty($grading_info->outcomes)) {\r
-//        foreach ($grading_info->outcomes as $n => $old) {\r
-//            $name = 'outcome_'.$n;\r
-//            if (isset($formdata->{$name}[$userid]) and $old->grades[$userid]->grade != $formdata->{$name}[$userid]) {\r
-//                $data[$n] = $formdata->{$name}[$userid];\r
-//            }\r
-//        }\r
-//    }\r
-//    if (count($data) > 0) {\r
-//        grade_update_outcomes('mod/basiclti', $course->id, 'mod', 'basiclti', $basiclti->id, $userid, $data);\r
-//    }\r
-//\r
-//}\r
-\r
-/**\r
- * Top-level function for handling of submissions called by submissions.php\r
- *\r
- * This is for handling the teacher interaction with the grading interface\r
- *\r
- * @global object\r
- * @param string $mode Specifies the kind of teacher interaction taking place\r
- */\r
-function lti_submissions($cm, $course, $basiclti, $mode) {\r
-    ///The main switch is changed to facilitate\r
-    ///1) Batch fast grading\r
-    ///2) Skip to the next one on the popup\r
-    ///3) Save and Skip to the next one on the popup\r
-\r
-    //make user global so we can use the id\r
-    global $USER, $OUTPUT, $DB;\r
-\r
-    $mailinfo = optional_param('mailinfo', null, PARAM_BOOL);\r
-\r
-    if (optional_param('next', null, PARAM_BOOL)) {\r
-        $mode='next';\r
-    }\r
-    if (optional_param('saveandnext', null, PARAM_BOOL)) {\r
-        $mode='saveandnext';\r
-    }\r
-\r
-    if (is_null($mailinfo)) {\r
-        if (optional_param('sesskey', null, PARAM_BOOL)) {\r
-            set_user_preference('lti_mailinfo', $mailinfo);\r
-        } else {\r
-            $mailinfo = get_user_preferences('lti_mailinfo', 0);\r
-        }\r
-    } else {\r
-        set_user_preference('lti_mailinfo', $mailinfo);\r
-    }\r
-\r
-    switch ($mode) {\r
-        case 'grade':                         // We are in a main window grading\r
-            if ($submission = process_feedback()) {\r
-                lti_display_submissions($cm, $course, $basiclti, get_string('changessaved'));\r
-            } else {\r
-                lti_display_submissions($cm, $course, $basiclti);\r
-            }\r
-            break;\r
-\r
-        case 'single':                        // We are in a main window displaying one submission\r
-            if ($submission = process_feedback()) {\r
-                lti_display_submissions($cm, $course, $basiclti, get_string('changessaved'));\r
-            } else {\r
-                display_submission();\r
-            }\r
-            break;\r
-\r
-        case 'all':                          // Main window, display everything\r
-            lti_display_submissions($cm, $course, $basiclti);\r
-            break;\r
-\r
-        case 'fastgrade':\r
-            /// do the fast grading stuff - this process should work for all 3 subclasses\r
-            $grading    = false;\r
-            $commenting = false;\r
-            $col        = false;\r
-            if (isset($_POST['submissioncomment'])) {\r
-                $col = 'submissioncomment';\r
-                $commenting = true;\r
-            }\r
-            if (isset($_POST['menu'])) {\r
-                $col = 'menu';\r
-                $grading = true;\r
-            }\r
-            if (!$col) {\r
-                //both submissioncomment and grade columns collapsed..\r
-                lti_display_submissions($cm, $course, $basiclti);\r
-                break;\r
-            }\r
-\r
-            foreach ($_POST[$col] as $id => $unusedvalue) {\r
-\r
-                $id = (int)$id; //clean parameter name\r
-\r
-                // Get grade item\r
-                $gradeitem = $DB->get_record('grade_items', array('courseid' => $cm->course, 'iteminstance' => $cm->instance));\r
-\r
-                // Get grade\r
-                $gradeentry = $DB->get_record('grade_grades', array('userid' => $id, 'itemid' => $gradeitem->id));\r
-\r
-                $grade = $_POST['menu'][$id];\r
-                $feedback = trim($_POST['submissioncomment'][$id]);\r
-\r
-                if ((!$gradeentry) && (($grade != '-1') || ($feedback != ''))) {\r
-                    $newsubmission = true;\r
-                } else {\r
-                    $newsubmission = false;\r
-                }\r
-\r
-                //for fast grade, we need to check if any changes take place\r
-                $updatedb = false;\r
-\r
-                if ($gradeentry) {\r
-                    if ($grading) {\r
-                        $grade = $_POST['menu'][$id];\r
-                        $updatedb = $updatedb || (($gradeentry->rawgrade != $grade) && ($gradeentry->rawgrade != '-1'));\r
-                        if ($grade != '-1') {\r
-                            $gradeentry->rawgrade = $grade;\r
-                            $gradeentry->finalgrade = $grade;\r
-                        } else {\r
-                            $gradeentry->rawgrade = null;\r
-                            $gradeentry->finalgrade = null;\r
-                        }\r
-                    } else {\r
-                        if (!$newsubmission) {\r
-                            unset($gradeentry->rawgrade);  // Don't need to update this.\r
-                        }\r
-                    }\r
-\r
-                    if ($commenting) {\r
-                        $commentvalue = trim($_POST['submissioncomment'][$id]);\r
-                        $updatedb = $updatedb || ($gradeentry->feedback != $commentvalue);\r
-                        // Special case\r
-                        if (($gradeentry->feedback == null) && ($commentvalue == "")) {\r
-                            unset($gradeentry->feedback);\r
-                        }\r
-                        $gradeentry->feedback = $commentvalue;\r
-                    } else {\r
-                        unset($gradeentry->feedback);  // Don't need to update this.\r
-                    }\r
-\r
-                } else { // No previous grade entry found\r
-                    if ($newsubmission) {\r
-                        if ($grade != '-1') {\r
-                            $gradeentry->rawgrade = $grade;\r
-                            $updatedb = true;\r
-                        }\r
-                        if ($feedback != '') {\r
-                            $gradeentry->feedback = $feedback;\r
-                            $updatedb = true;\r
-                        }\r
-                    }\r
-                }\r
-\r
-                $gradeentry->usermodified    = $USER->id;\r
-                if (!$gradeentry->timecreated) {\r
-                    $gradeentry->timecreated = time();\r
-                }\r
-                $gradeentry->timemodified = time();\r
-\r
-                //if it is not an update, we don't change the last modified time etc.\r
-                //this will also not write into database if no submissioncomment and grade is entered.\r
-                if ($updatedb) {\r
-                    if ($gradeentry->rawgrade == '-1') {\r
-                        $gradeentry->rawgrade = null;\r
-                    }\r
-\r
-                    if ($newsubmission) {\r
-                        if (!isset($gradeentry->feedback)) {\r
-                            $gradeentry->feedback = '';\r
-                        }\r
-                        $gradeentry->itemid = $gradeitem->id;\r
-                        $gradeentry->userid = $id;\r
-                        $sid = $DB->insert_record("grade_grades", $gradeentry);\r
-                        $gradeentry->id = $sid;\r
-                    } else {\r
-                        $DB->update_record("grade_grades", $gradeentry);\r
-                    }\r
-\r
-                    //add to log only if updating\r
-                    add_to_log($course->id, 'lti', 'update grades',\r
-                               'submissions.php?id='.$cm->id.'&user='.$USER->id,\r
-                               $USER->id, $cm->id);\r
-                }\r
-\r
-            }\r
-\r
-            $message = $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');\r
-\r
-            lti_display_submissions($cm, $course, $basiclti, $message);\r
-            break;\r
-\r
-        case 'saveandnext':\r
-            ///We are in pop up. save the current one and go to the next one.\r
-            //first we save the current changes\r
-            if ($submission = process_feedback()) {\r
-                //print_heading(get_string('changessaved'));\r
-                //$extra_javascript = $this->update_main_listing($submission);\r
-            }\r
-\r
-        case 'next':\r
-            /// We are currently in pop up, but we want to skip to next one without saving.\r
-            ///    This turns out to be similar to a single case\r
-            /// The URL used is for the next submission.\r
-            $offset = required_param('offset', PARAM_INT);\r
-            $nextid = required_param('nextid', PARAM_INT);\r
-            $id = required_param('id', PARAM_INT);\r
-            $offset = (int)$offset+1;\r
-            //$this->display_submission($offset+1 , $nextid);\r
-            redirect('submissions.php?id='.$id.'&userid='. $nextid . '&mode=single&offset='.$offset);\r
-            break;\r
-\r
-        case 'singlenosave':\r
-            display_submission();\r
-            break;\r
-\r
-        default:\r
-            echo "Critical error. Something is seriously wrong!!";\r
-            break;\r
-    }\r
-}\r
-\r
-/**\r
- *  Display all the submissions ready for grading\r
- *\r
- * @global object\r
- * @global object\r
- * @global object\r
- * @global object\r
- * @param string $message\r
- * @return bool|void\r
- */\r
-function lti_display_submissions($cm, $course, $basiclti, $message='') {\r
-    global $CFG, $DB, $OUTPUT, $PAGE;\r
-    require_once($CFG->libdir.'/gradelib.php');\r
-\r
-    /* first we check to see if the form has just been submitted\r
-     * to request user_preference updates\r
-     */\r
-    $updatepref = optional_param('updatepref', 0, PARAM_INT);\r
-\r
-    if (isset($_POST['updatepref'])) {\r
-        $perpage = optional_param('perpage', 10, PARAM_INT);\r
-        $perpage = ($perpage <= 0) ? 10 : $perpage;\r
-        $filter = optional_param('filter', 0, PARAM_INT);\r
-        set_user_preference('lti_perpage', $perpage);\r
-        set_user_preference('lti_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL));\r
-        set_user_preference('lti_filter', $filter);\r
-    }\r
-\r
-    /* next we get perpage and quickgrade (allow quick grade) params\r
-     * from database\r
-     */\r
-    $perpage    = get_user_preferences('lti_perpage', 10);\r
-    $quickgrade = get_user_preferences('lti_quickgrade', 0);\r
-    $filter = get_user_preferences('lti_filter', 0);\r
-    $grading_info = grade_get_grades($course->id, 'mod', 'lti', $basiclti->id);\r
-\r
-    if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) {\r
-        $uses_outcomes = true;\r
-    } else {\r
-        $uses_outcomes = false;\r
-    }\r
-\r
-    $page    = optional_param('page', 0, PARAM_INT);\r
-    $strsaveallfeedback = get_string('saveallfeedback', 'lti');\r
-\r
-    $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet\r
-    add_to_log($course->id, 'lti', 'view submission', 'submissions.php?id='.$cm->id, $basiclti->id, $cm->id);\r
-\r
-    $PAGE->set_title(format_string($basiclti->name, true));\r
-    $PAGE->set_heading($course->fullname);\r
-    echo $OUTPUT->header();\r
-\r
-    echo '<div class="usersubmissions">';\r
-\r
-    //hook to allow plagiarism plugins to update status/print links.\r
-    plagiarism_update_status($course, $cm);\r
-\r
-    /// Print quickgrade form around the table\r
-    if ($quickgrade) {\r
-        $formattrs = array();\r
-        $formattrs['action'] = new moodle_url('/mod/lti/submissions.php');\r
-        $formattrs['id'] = 'fastg';\r
-        $formattrs['method'] = 'post';\r
-\r
-        echo html_writer::start_tag('form', $formattrs);\r
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id',      'value'=> $cm->id));\r
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'mode',    'value'=> 'fastgrade'));\r
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'page',    'value'=> $page));\r
-        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=> sesskey()));\r
-    }\r
-\r
-    $course_context = get_context_instance(CONTEXT_COURSE, $course->id);\r
-    if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) {\r
-        echo '<div class="allcoursegrades"><a href="' . $CFG->wwwroot . '/grade/report/grader/index.php?id=' . $course->id . '">'\r
-            . get_string('seeallcoursegrades', 'grades') . '</a></div>';\r
-    }\r
-\r
-    if (!empty($message)) {\r
-        echo $message;   // display messages here if any\r
-    }\r
-\r
-    $context = get_context_instance(CONTEXT_MODULE, $cm->id);\r
-\r
-/// Check to see if groups are being used in this tool\r
-\r
-    /// find out current groups mode\r
-    $groupmode = groups_get_activity_groupmode($cm);\r
-    $currentgroup = groups_get_activity_group($cm, true);\r
-    groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/lti/submissions.php?id=' . $cm->id);\r
-\r
-    /// Get all ppl that are allowed to submit tools\r
-    list($esql, $params) = get_enrolled_sql($context, 'mod/lti:view', $currentgroup);\r
-\r
-    $sql = "SELECT u.id FROM {user} u ".\r
-           "LEFT JOIN ($esql) eu ON eu.id=u.id ".\r
-           "WHERE u.deleted = 0 AND eu.id=u.id ";\r
-\r
-    $users = $DB->get_records_sql($sql, $params);\r
-    if (!empty($users)) {\r
-        $users = array_keys($users);\r
-    }\r
-\r
-    // if groupmembersonly used, remove users who are not in any group\r
-    if ($users and !empty($CFG->enablegroupmembersonly) and $cm->groupmembersonly) {\r
-        if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {\r
-            $users = array_intersect($users, array_keys($groupingusers));\r
-        }\r
-    }\r
-\r
-    $tablecolumns = array('picture', 'fullname', 'grade', 'submissioncomment', 'timemodified', 'timemarked', 'status', 'finalgrade');\r
-    if ($uses_outcomes) {\r
-        $tablecolumns[] = 'outcome'; // no sorting based on outcomes column\r
-    }\r
-\r
-    $tableheaders = array('',\r
-                          get_string('fullname'),\r
-                          get_string('grade'),\r
-                          get_string('comment', 'lti'),\r
-                          get_string('lastmodified').' ('.get_string('submission', 'lti').')',\r
-                          get_string('lastmodified').' ('.get_string('grade').')',\r
-                          get_string('status'),\r
-                          get_string('finalgrade', 'grades'));\r
-    if ($uses_outcomes) {\r
-        $tableheaders[] = get_string('outcome', 'grades');\r
-    }\r
-\r
-    require_once($CFG->libdir.'/tablelib.php');\r
-    $table = new flexible_table('mod-lti-submissions');\r
-\r
-    $table->define_columns($tablecolumns);\r
-    $table->define_headers($tableheaders);\r
-    $table->define_baseurl($CFG->wwwroot.'/mod/lti/submissions.php?id='.$cm->id.'&amp;currentgroup='.$currentgroup);\r
-\r
-    $table->sortable(true, 'lastname');//sorted by lastname by default\r
-    $table->collapsible(true);\r
-    $table->initialbars(true);\r
-\r
-    $table->column_suppress('picture');\r
-    $table->column_suppress('fullname');\r
-\r
-    $table->column_class('picture', 'picture');\r
-    $table->column_class('fullname', 'fullname');\r
-    $table->column_class('grade', 'grade');\r
-    $table->column_class('submissioncomment', 'comment');\r
-    $table->column_class('timemodified', 'timemodified');\r
-    $table->column_class('timemarked', 'timemarked');\r
-    $table->column_class('status', 'status');\r
-    $table->column_class('finalgrade', 'finalgrade');\r
-    if ($uses_outcomes) {\r
-        $table->column_class('outcome', 'outcome');\r
-    }\r
-\r
-    $table->set_attribute('cellspacing', '0');\r
-    $table->set_attribute('id', 'attempts');\r
-    $table->set_attribute('class', 'submissions');\r
-    $table->set_attribute('width', '100%');\r
-\r
-    $table->no_sorting('finalgrade');\r
-    $table->no_sorting('outcome');\r
-\r
-    // Start working -- this is necessary as soon as the niceties are over\r
-    $table->setup();\r
-\r
-    if (empty($users)) {\r
-        echo $OUTPUT->heading(get_string('noviewusers', 'lti'));\r
-        echo '</div>';\r
-        return true;\r
-    }\r
-\r
-       /// Construct the SQL\r
-    list($where, $params) = $table->get_sql_where();\r
-    if ($where) {\r
-        $where .= ' AND ';\r
-    }\r
-\r
-    if ($sort = $table->get_sql_sort()) {\r
-        $sort = ' ORDER BY '.$sort;\r
-    }\r
-\r
-    $ufields = user_picture::fields('u');\r
-\r
-    $gradeitem = $DB->get_record('grade_items', array('courseid' => $cm->course, 'iteminstance' => $cm->instance));\r
-\r
-    $select = "SELECT $ufields,\r
-              g.rawgrade, g.feedback,\r
-              g.timemodified, g.timecreated ";\r
-\r
-    $sql = 'FROM {user} u'.\r
-            ' LEFT JOIN {grade_grades} g ON u.id = g.userid AND g.itemid = '.$gradeitem->id.\r
-            ' LEFT JOIN {grade_items} i ON g.itemid = i.id'.\r
-            ' AND i.iteminstance = '.$basiclti->id.\r
-            ' WHERE '.$where.'u.id IN ('.implode(',', $users).') ';\r
-\r
-    $ausers = $DB->get_records_sql($select.$sql.$sort, $params, $table->get_page_start(), $table->get_page_size());\r
-\r
-    $table->pagesize($perpage, count($users));\r
-\r
-    ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next\r
-    $offset = $page * $perpage;\r
-    $strupdate = get_string('update');\r
-    $strgrade  = get_string('grade');\r
-    $grademenu = make_grades_menu($basiclti->grade);\r
-    if ($ausers !== false) {\r
-        $grading_info = grade_get_grades($course->id, 'mod', 'lti', $basiclti->id, array_keys($ausers));\r
-        $endposition = $offset + $perpage;\r
-        $currentposition = 0;\r
-        foreach ($ausers as $auser) {\r
-\r
-            if ($auser->timemodified > 0) {\r
-                $timemodified = '<div id="ts'.$auser->id.'">'.userdate($auser->timemodified).'</div>';\r
-            } else {\r
-                $timemodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';\r
-            }\r
-            if ($auser->timecreated > 0) {\r
-                $timecreated = '<div id="ts'.$auser->id.'">'.userdate($auser->timecreated).'</div>';\r
-            } else {\r
-                $timecreated = '<div id="ts'.$auser->id.'">&nbsp;</div>';\r
-            }\r
-\r
-            if ($currentposition == $offset && $offset < $endposition) {\r
-                $final_grade = $grading_info->items[0]->grades[$auser->id];\r
-                $grademax = $grading_info->items[0]->grademax;\r
-                $final_grade->formatted_grade = round($final_grade->grade, 2) .' / ' . round($grademax, 2);\r
-                $locked_overridden = 'locked';\r
-                if ($final_grade->overridden) {\r
-                    $locked_overridden = 'overridden';\r
-                }\r
-\r
-                /// Calculate user status\r
-                $picture = $OUTPUT->user_picture($auser);\r
-\r
-                $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';\r
-                $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';\r
-                $status          = '<div id="st'.$auser->id.'">&nbsp;</div>';\r
-\r
-                if ($final_grade->locked or $final_grade->overridden) {\r
-                    $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade . '</div>';\r
-                } else if ($quickgrade) {   // allow editing\r
-                    $attributes = array();\r
-                    $attributes['tabindex'] = $tabindex++;\r
-                    if ($auser->rawgrade != "") {\r
-                        $menu = html_writer::select(make_grades_menu($basiclti->grade), 'menu['.$auser->id.']', round($auser->rawgrade, 0), array(-1=>get_string('nograde')), $attributes);\r
-                    } else {\r
-                        $menu = html_writer::select(make_grades_menu($basiclti->grade), 'menu['.$auser->id.']', -1, array(-1=>get_string('nograde')), $attributes);\r
-                    }\r
-                    $grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';\r
-                } else if ($final_grade->grade) {\r
-                    if ($auser->rawgrade != "") {\r
-                        $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade.'</div>';\r
-                    } else {\r
-                        $grade = '<div id="g'.$auser->id.'">-1</div>';\r
-                    }\r
-\r
-                } else {\r
-                    $grade = '<div id="g'.$auser->id.'">No Grade</div>';\r
-                }\r
-\r
-                if ($final_grade->locked or $final_grade->overridden) {\r
-                    $comment = '<div id="com'.$auser->id.'">'.$final_grade->str_feedback.'</div>';\r
-                } else if ($quickgrade) {\r
-                    $comment = '<div id="com'.$auser->id.'">'\r
-                             . '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'\r
-                             . $auser->id.'" rows="2" cols="20">'.($auser->feedback).'</textarea></div>';\r
-                } else {\r
-                    $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->feedback), 15).'</div>';\r
-                }\r
-\r
-                if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1\r
-                    $auser->status = 0;\r
-                } else {\r
-                    $auser->status = 1;\r
-                }\r
-\r
-                $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;\r
-\r
-                ///No more buttons, we use popups ;-).\r
-                $popup_url = '/mod/lti/submissions.php?id='.$cm->id\r
-                           . '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;filter='.$filter.'&amp;offset='.$offset++;\r
-\r
-                $button = $OUTPUT->action_link($popup_url, $buttontext);\r
-\r
-                $status  = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';\r
-\r
-                $finalgrade = '<span id="finalgrade_'.$auser->id.'">'.$final_grade->str_grade.'</span>';\r
-\r
-                $outcomes = '';\r
-\r
-                if ($uses_outcomes) {\r
-\r
-                    foreach ($grading_info->outcomes as $n => $outcome) {\r
-                        $outcomes .= '<div class="outcome"><label>'.$outcome->name.'</label>';\r
-                        $options = make_grades_menu(-$outcome->scaleid);\r
-\r
-                        if ($outcome->grades[$auser->id]->locked or !$quickgrade) {\r
-                            $options[0] = get_string('nooutcome', 'grades');\r
-                            $outcomes .= ': <span id="outcome_'.$n.'_'.$auser->id.'">'.$options[$outcome->grades[$auser->id]->grade].'</span>';\r
-                        } else {\r
-                            $attributes = array();\r
-                            $attributes['tabindex'] = $tabindex++;\r
-                            $attributes['id'] = 'outcome_'.$n.'_'.$auser->id;\r
-                            $outcomes .= ' '.html_writer::select($options, 'outcome_'.$n.'['.$auser->id.']', $outcome->grades[$auser->id]->grade, array(0=>get_string('nooutcome', 'grades')), $attributes);\r
-                        }\r
-                        $outcomes .= '</div>';\r
-                    }\r
-                }\r
-\r
-                $userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser, has_capability('moodle/site:viewfullnames', $context)) . '</a>';\r
-                $row = array($picture, $userlink, $grade, $comment, $timemodified, $timecreated, $status, $finalgrade);\r
-                if ($uses_outcomes) {\r
-                    $row[] = $outcomes;\r
-                }\r
-\r
-                $table->add_data($row);\r
-            }\r
-            $currentposition++;\r
-        }\r
-    }\r
-\r
-    $table->print_html();  /// Print the whole table\r
-\r
-    /// Print quickgrade form around the table\r
-    if ($quickgrade && $table->started_output) {\r
-        $mailinfopref = false;\r
-        if (get_user_preferences('lti_mailinfo', 1)) {\r
-            $mailinfopref = true;\r
-        }\r
-        $emailnotification =  html_writer::checkbox('mailinfo', 1, $mailinfopref, get_string('enableemailnotification', 'lti'));\r
-\r
-        $emailnotification .= $OUTPUT->help_icon('enableemailnotification', 'lti');\r
-        echo html_writer::tag('div', $emailnotification, array('class'=>'emailnotification'));\r
-\r
-        $savefeedback = html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'fastg', 'value'=>get_string('saveallfeedback', 'lti')));\r
-        echo html_writer::tag('div', $savefeedback, array('class'=>'fastgbutton'));\r
-\r
-        echo html_writer::end_tag('form');\r
-    } else if ($quickgrade) {\r
-        echo html_writer::end_tag('form');\r
-    }\r
-\r
-    echo '</div>';\r
-    /// End of fast grading form\r
-\r
-    /// Mini form for setting user preference\r
-\r
-    $formaction = new moodle_url('/mod/lti/submissions.php', array('id'=>$cm->id));\r
-    $mform = new MoodleQuickForm('optionspref', 'post', $formaction, '', array('class'=>'optionspref'));\r
-\r
-    $mform->addElement('hidden', 'updatepref');\r
-    $mform->setDefault('updatepref', 1);\r
-    $mform->addElement('header', 'qgprefs', get_string('optionalsettings', 'lti'));\r
-//        $mform->addElement('select', 'filter', get_string('show'),  $filters);\r
-\r
-    $mform->setDefault('filter', $filter);\r
-\r
-    $mform->addElement('text', 'perpage', get_string('pagesize', 'lti'), array('size'=>1));\r
-    $mform->setDefault('perpage', $perpage);\r
-\r
-    $mform->addElement('checkbox', 'quickgrade', get_string('quickgrade', 'lti'));\r
-    $mform->setDefault('quickgrade', $quickgrade);\r
-    $mform->addHelpButton('quickgrade', 'quickgrade', 'lti');\r
-\r
-    $mform->addElement('submit', 'savepreferences', get_string('savepreferences'));\r
-\r
-    $mform->display();\r
-\r
-    echo $OUTPUT->footer();\r
-}\r
-\r
-/**\r
- * Create grade item for given basiclti\r
- *\r
- * @param object $basiclti object with extra cmidnumber\r
- * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook\r
- * @return int 0 if ok, error code otherwise\r
- */\r
-function lti_grade_item_update($basiclti, $grades=null) {\r
-    global $CFG;\r
-    require_once($CFG->libdir.'/gradelib.php');\r
-\r
-    $params = array('itemname'=>$basiclti->name, 'idnumber'=>$basiclti->cmidnumber);\r
-\r
-    if ($basiclti->grade > 0) {\r
-        $params['gradetype'] = GRADE_TYPE_VALUE;\r
-        $params['grademax']  = $basiclti->grade;\r
-        $params['grademin']  = 0;\r
-\r
-    } else if ($basiclti->grade < 0) {\r
-        $params['gradetype'] = GRADE_TYPE_SCALE;\r
-        $params['scaleid']   = -$basiclti->grade;\r
-\r
-    } else {\r
-        $params['gradetype'] = GRADE_TYPE_TEXT; // allow text comments only\r
-    }\r
-\r
-    if ($grades  === 'reset') {\r
-        $params['reset'] = true;\r
-        $grades = null;\r
-    }\r
-\r
-    return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, $grades, $params);\r
-}\r
-\r
-/**\r
- * Delete grade item for given basiclti\r
- *\r
- * @param object $basiclti object\r
- * @return object basiclti\r
- */\r
-function lti_grade_item_delete($basiclti) {\r
-    global $CFG;\r
-    require_once($CFG->libdir.'/gradelib.php');\r
-\r
-    return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, null, array('deleted'=>1));\r
-}\r
-\r
+<?php
+// This file is part of BasicLTI4Moodle
+//
+// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)
+// consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web
+// based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI
+// specification is part of the IMS standard Common Cartridge 1.1 Sakai and other main LMS
+// are already supporting or going to support BasicLTI. This project Implements the consumer
+// for Moodle. Moodle is a Free Open source Learning Management System by Martin Dougiamas.
+// BasicLTI4Moodle is a project iniciated and leaded by Ludo(Marc Alier) and Jordi Piguillem
+// at the GESSI research group at UPC.
+// SimpleLTI consumer for Moodle is an implementation of the early specification of LTI
+// by Charles Severance (Dr Chuck) htp://dr-chuck.com , developed by Jordi Piguillem in a
+// Google Summer of Code 2008 project co-mentored by Charles Severance and Marc Alier.
+//
+// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
+// of the Universitat Politecnica de Catalunya http://www.upc.edu
+// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
+//
+// 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 a library of functions and constants for the
+ * BasicLTI module
+ *
+ * @package lti
+ * @copyright 2009 Marc Alier, Jordi Piguillem, Nikolas Galanis
+ *  marc.alier@upc.edu
+ * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu
+ *
+ * @author Marc Alier
+ * @author Jordi Piguillem
+ * @author Nikolas Galanis
+ *
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die;
+
+require_once($CFG->dirroot.'/mod/lti/locallib.php');
+
+/**
+ * List of features supported in URL module
+ * @param string $feature FEATURE_xx constant for requested feature
+ * @return mixed True if module supports feature, false if not, null if doesn't know
+ */
+function lti_supports($feature) {
+    switch($feature) {
+        case FEATURE_GROUPS:                  return false;
+        case FEATURE_GROUPINGS:               return false;
+        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;
+
+        default: return null;
+    }
+}
+
+/**
+ * Given an object containing all the necessary data,
+ * (defined by the form in mod.html) this function
+ * will create a new instance and return the id number
+ * of the new instance.
+ *
+ * @param object $instance An object from the form in mod.html
+ * @return int The id of the newly inserted basiclti record
+ **/
+function lti_add_instance($formdata) {
+    global $DB;
+    $formdata->timecreated = time();
+    $formdata->timemodified = $formdata->timecreated;
+    $formdata->servicesalt = uniqid('', true);
+    
+    if(!isset($formdata->grade)){
+        $formdata->grade = 100;
+    }
+    
+    $id = $DB->insert_record("lti", $formdata);
+
+    if ($formdata->instructorchoiceacceptgrades == 1) {
+        $basiclti = $DB->get_record('lti', array('id'=>$id));
+        $basiclti->cmidnumber = $formdata->cmidnumber;
+        
+        lti_grade_item_update($basiclti);
+    }
+
+    return $id;
+}
+
+/**
+ * Given an object containing all the necessary data,
+ * (defined by the form in mod.html) this function
+ * will update an existing instance with new data.
+ *
+ * @param object $instance An object from the form in mod.html
+ * @return boolean Success/Fail
+ **/
+function lti_update_instance($formdata) {
+    global $DB;
+
+    $formdata->timemodified = time();
+    $formdata->id = $formdata->instance;
+
+    if(!isset($formdata->showtitle)){
+        $formdata->showtitle = 0;
+    }
+    
+    if(!isset($formdata->showdescription)){
+        $formdata->showdescription = 0;
+    }
+    
+    if ($formdata->instructorchoiceacceptgrades == 1) {
+        $basicltirec = $DB->get_record("lti", array("id" => $formdata->id));
+        $basicltirec->cmidnumber = $formdata->cmidnumber;
+        
+        lti_grade_item_update($basicltirec);
+    } else {
+        lti_grade_item_delete($formdata);
+    }
+
+    return $DB->update_record("lti", $formdata);
+}
+
+/**
+ * Given an ID of an instance of this module,
+ * this function will permanently delete the instance
+ * and any data that depends on it.
+ *
+ * @param int $id Id of the module instance
+ * @return boolean Success/Failure
+ **/
+function lti_delete_instance($id) {
+    global $DB;
+
+    if (! $basiclti = $DB->get_record("lti", array("id" => $id))) {
+        return false;
+    }
+
+    $result = true;
+
+    # Delete any dependent records here #
+    lti_grade_item_delete($basiclti);
+
+    return $DB->delete_records("lti", array("id" => $basiclti->id));
+}
+
+/**
+ * Return a small object with summary information about what a
+ * user has done with a given particular instance of this module
+ * Used for user activity reports.
+ * $return->time = the time they did it
+ * $return->info = a short text description
+ *
+ * @return null
+ * @TODO: implement this moodle function (if needed)
+ **/
+function lti_user_outline($course, $user, $mod, $basiclti) {
+    return $return;
+}
+
+/**
+ * Print a detailed representation of what a user has done with
+ * a given particular instance of this module, for user activity reports.
+ *
+ * @return boolean
+ * @TODO: implement this moodle function (if needed)
+ **/
+function lti_user_complete($course, $user, $mod, $basiclti) {
+    return true;
+}
+
+/**
+ * Given a course and a time, this module should find recent activity
+ * that has occurred in basiclti activities and print it out.
+ * Return true if there was output, or false is there was none.
+ *
+ * @uses $CFG
+ * @return boolean
+ * @TODO: implement this moodle function
+ **/
+function lti_print_recent_activity($course, $isteacher, $timestart) {
+    return false;  //  True if anything was printed, otherwise false
+}
+
+/**
+ * Function to be run periodically according to the moodle cron
+ * This function searches for things that need to be done, such
+ * as sending out mail, toggling flags etc ...
+ *
+ * @uses $CFG
+ * @return boolean
+ **/
+function lti_cron () {
+    return true;
+}
+
+/**
+ * Must return an array of grades for a given instance of this module,
+ * indexed by user.  It also returns a maximum allowed grade.
+ *
+ * Example:
+ *    $return->grades = array of grades;
+ *    $return->maxgrade = maximum allowed grade;
+ *
+ *    return $return;
+ *
+ * @param int $basicltiid ID of an instance of this module
+ * @return mixed Null or object with an array of grades and with the maximum grade
+ *
+ * @TODO: implement this moodle function (if needed)
+ **/
+function lti_grades($basicltiid) {
+    return null;
+}
+
+/**
+ * Must return an array of user records (all data) who are participants
+ * for a given instance of basiclti. Must include every user involved
+ * in the instance, independient of his role (student, teacher, admin...)
+ * See other modules as example.
+ *
+ * @param int $basicltiid ID of an instance of this module
+ * @return mixed boolean/array of students
+ *
+ * @TODO: implement this moodle function
+ **/
+function lti_get_participants($basicltiid) {
+    return false;
+}
+
+/**
+ * This function returns if a scale is being used by one basiclti
+ * it it has support for grading and scales. Commented code should be
+ * modified if necessary. See forum, glossary or journal modules
+ * as reference.
+ *
+ * @param int $basicltiid ID of an instance of this module
+ * @return mixed
+ *
+ * @TODO: implement this moodle function (if needed)
+ **/
+function lti_scale_used ($basicltiid, $scaleid) {
+    $return = false;
+
+    //$rec = get_record("basiclti","id","$basicltiid","scale","-$scaleid");
+    //
+    //if (!empty($rec)  && !empty($scaleid)) {
+    //    $return = true;
+    //}
+
+    return $return;
+}
+
+/**
+ * Checks if scale is being used by any instance of basiclti.
+ * This function was added in 1.9
+ *
+ * This is used to find out if scale used anywhere
+ * @param $scaleid int
+ * @return boolean True if the scale is used by any basiclti
+ *
+ */
+function lti_scale_used_anywhere($scaleid) {
+    global $DB;
+
+    if ($scaleid and $DB->record_exists('lti', array('grade' => -$scaleid))) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/**
+ * Execute post-install custom actions for the module
+ * This function was added in 1.9
+ *
+ * @return boolean true if success, false on error
+ */
+function lti_install() {
+     return true;
+}
+
+/**
+ * Execute post-uninstall custom actions for the module
+ * This function was added in 1.9
+ *
+ * @return boolean true if success, false on error
+ */
+function lti_uninstall() {
+    return true;
+}
+
+/**
+ * Returns available Basic LTI types
+ *
+ * @return array of basicLTI types
+ */
+function lti_get_lti_types() {
+    global $DB;
+
+    return $DB->get_records('lti_types');
+}
+
+/**
+ * Returns Basic LTI types configuration
+ *
+ * @return array of basicLTI types
+ */
+/*function lti_get_types() {
+    $types = array();
+
+    $basicltitypes = lti_get_lti_types();
+    if (!empty($basicltitypes)) {
+        foreach ($basicltitypes as $basicltitype) {
+            $ltitypesconfig = lti_get_type_config($basicltitype->id);
+
+            $modclass = MOD_CLASS_ACTIVITY;
+            if (isset($ltitypesconfig['module_class_type'])) {
+                if ($ltitypesconfig['module_class_type']=='1') {
+                    $modclass = MOD_CLASS_RESOURCE;
+                }
+            }
+
+            $type = new object();
+            $type->modclass = $modclass;
+            $type->type = 'lti&amp;type='.urlencode($basicltitype->rawname);
+            $type->typestr = $basicltitype->name;
+            $types[] = $type;
+        }
+    }
+
+    return $types;
+}*/
+
+//////////////////////////////////////////////////////////////////////////////////////
+/// Any other basiclti functions go here.  Each of them must have a name that
+/// starts with basiclti_
+/// Remember (see note in first lines) that, if this section grows, it's HIGHLY
+/// recommended to move all funcions below to a new "localib.php" file.
+
+///**
+// *
+// */
+//function process_outcomes($userid, $course, $basiclti) {
+//    global $CFG, $USER;
+//
+//    if (empty($CFG->enableoutcomes)) {
+//        return;
+//    }
+//
+//    require_once($CFG->libdir.'/gradelib.php');
+//
+//    if (!$formdata = data_submitted() or !confirm_sesskey()) {
+//        return;
+//    }
+//
+//    $data = array();
+//    $grading_info = grade_get_grades($course->id, 'mod', 'basiclti', $basiclti->id, $userid);
+//
+//    if (!empty($grading_info->outcomes)) {
+//        foreach ($grading_info->outcomes as $n => $old) {
+//            $name = 'outcome_'.$n;
+//            if (isset($formdata->{$name}[$userid]) and $old->grades[$userid]->grade != $formdata->{$name}[$userid]) {
+//                $data[$n] = $formdata->{$name}[$userid];
+//            }
+//        }
+//    }
+//    if (count($data) > 0) {
+//        grade_update_outcomes('mod/basiclti', $course->id, 'mod', 'basiclti', $basiclti->id, $userid, $data);
+//    }
+//
+//}
+
+/**
+ * Top-level function for handling of submissions called by submissions.php
+ *
+ * This is for handling the teacher interaction with the grading interface
+ *
+ * @global object
+ * @param string $mode Specifies the kind of teacher interaction taking place
+ */
+function lti_submissions($cm, $course, $basiclti, $mode) {
+    ///The main switch is changed to facilitate
+    ///1) Batch fast grading
+    ///2) Skip to the next one on the popup
+    ///3) Save and Skip to the next one on the popup
+
+    //make user global so we can use the id
+    global $USER, $OUTPUT, $DB;
+
+    $mailinfo = optional_param('mailinfo', null, PARAM_BOOL);
+
+    if (optional_param('next', null, PARAM_BOOL)) {
+        $mode='next';
+    }
+    if (optional_param('saveandnext', null, PARAM_BOOL)) {
+        $mode='saveandnext';
+    }
+
+    if (is_null($mailinfo)) {
+        if (optional_param('sesskey', null, PARAM_BOOL)) {
+            set_user_preference('lti_mailinfo', $mailinfo);
+        } else {
+            $mailinfo = get_user_preferences('lti_mailinfo', 0);
+        }
+    } else {
+        set_user_preference('lti_mailinfo', $mailinfo);
+    }
+
+    switch ($mode) {
+        case 'grade':                         // We are in a main window grading
+            if ($submission = process_feedback()) {
+                lti_display_submissions($cm, $course, $basiclti, get_string('changessaved'));
+            } else {
+                lti_display_submissions($cm, $course, $basiclti);
+            }
+            break;
+
+        case 'single':                        // We are in a main window displaying one submission
+            if ($submission = process_feedback()) {
+                lti_display_submissions($cm, $course, $basiclti, get_string('changessaved'));
+            } else {
+                display_submission();
+            }
+            break;
+
+        case 'all':                          // Main window, display everything
+            lti_display_submissions($cm, $course, $basiclti);
+            break;
+
+        case 'fastgrade':
+            /// do the fast grading stuff - this process should work for all 3 subclasses
+            $grading    = false;
+            $commenting = false;
+            $col        = false;
+            if (isset($_POST['submissioncomment'])) {
+                $col = 'submissioncomment';
+                $commenting = true;
+            }
+            if (isset($_POST['menu'])) {
+                $col = 'menu';
+                $grading = true;
+            }
+            if (!$col) {
+                //both submissioncomment and grade columns collapsed..
+                lti_display_submissions($cm, $course, $basiclti);
+                break;
+            }
+
+            foreach ($_POST[$col] as $id => $unusedvalue) {
+
+                $id = (int)$id; //clean parameter name
+
+                // Get grade item
+                $gradeitem = $DB->get_record('grade_items', array('courseid' => $cm->course, 'iteminstance' => $cm->instance));
+
+                // Get grade
+                $gradeentry = $DB->get_record('grade_grades', array('userid' => $id, 'itemid' => $gradeitem->id));
+
+                $grade = $_POST['menu'][$id];
+                $feedback = trim($_POST['submissioncomment'][$id]);
+
+                if ((!$gradeentry) && (($grade != '-1') || ($feedback != ''))) {
+                    $newsubmission = true;
+                } else {
+                    $newsubmission = false;
+                }
+
+                //for fast grade, we need to check if any changes take place
+                $updatedb = false;
+
+                if ($gradeentry) {
+                    if ($grading) {
+                        $grade = $_POST['menu'][$id];
+                        $updatedb = $updatedb || (($gradeentry->rawgrade != $grade) && ($gradeentry->rawgrade != '-1'));
+                        if ($grade != '-1') {
+                            $gradeentry->rawgrade = $grade;
+                            $gradeentry->finalgrade = $grade;
+                        } else {
+                            $gradeentry->rawgrade = null;
+                            $gradeentry->finalgrade = null;
+                        }
+                    } else {
+                        if (!$newsubmission) {
+                            unset($gradeentry->rawgrade);  // Don't need to update this.
+                        }
+                    }
+
+                    if ($commenting) {
+                        $commentvalue = trim($_POST['submissioncomment'][$id]);
+                        $updatedb = $updatedb || ($gradeentry->feedback != $commentvalue);
+                        // Special case
+                        if (($gradeentry->feedback == null) && ($commentvalue == "")) {
+                            unset($gradeentry->feedback);
+                        }
+                        $gradeentry->feedback = $commentvalue;
+                    } else {
+                        unset($gradeentry->feedback);  // Don't need to update this.
+                    }
+
+                } else { // No previous grade entry found
+                    if ($newsubmission) {
+                        if ($grade != '-1') {
+                            $gradeentry->rawgrade = $grade;
+                            $updatedb = true;
+                        }
+                        if ($feedback != '') {
+                            $gradeentry->feedback = $feedback;
+                            $updatedb = true;
+                        }
+                    }
+                }
+
+                $gradeentry->usermodified    = $USER->id;
+                if (!$gradeentry->timecreated) {
+                    $gradeentry->timecreated = time();
+                }
+                $gradeentry->timemodified = time();
+
+                //if it is not an update, we don't change the last modified time etc.
+                //this will also not write into database if no submissioncomment and grade is entered.
+                if ($updatedb) {
+                    if ($gradeentry->rawgrade == '-1') {
+                        $gradeentry->rawgrade = null;
+                    }
+
+                    if ($newsubmission) {
+                        if (!isset($gradeentry->feedback)) {
+                            $gradeentry->feedback = '';
+                        }
+                        $gradeentry->itemid = $gradeitem->id;
+                        $gradeentry->userid = $id;
+                        $sid = $DB->insert_record("grade_grades", $gradeentry);
+                        $gradeentry->id = $sid;
+                    } else {
+                        $DB->update_record("grade_grades", $gradeentry);
+                    }
+
+                    //add to log only if updating
+                    add_to_log($course->id, 'lti', 'update grades',
+                               'submissions.php?id='.$cm->id.'&user='.$USER->id,
+                               $USER->id, $cm->id);
+                }
+
+            }
+
+            $message = $OUTPUT->notification(get_string('changessaved'), 'notifysuccess');
+
+            lti_display_submissions($cm, $course, $basiclti, $message);
+            break;
+
+        case 'saveandnext':
+            ///We are in pop up. save the current one and go to the next one.
+            //first we save the current changes
+            if ($submission = process_feedback()) {
+                //print_heading(get_string('changessaved'));
+                //$extra_javascript = $this->update_main_listing($submission);
+            }
+
+        case 'next':
+            /// We are currently in pop up, but we want to skip to next one without saving.
+            ///    This turns out to be similar to a single case
+            /// The URL used is for the next submission.
+            $offset = required_param('offset', PARAM_INT);
+            $nextid = required_param('nextid', PARAM_INT);
+            $id = required_param('id', PARAM_INT);
+            $offset = (int)$offset+1;
+            //$this->display_submission($offset+1 , $nextid);
+            redirect('submissions.php?id='.$id.'&userid='. $nextid . '&mode=single&offset='.$offset);
+            break;
+
+        case 'singlenosave':
+            display_submission();
+            break;
+
+        default:
+            echo "Critical error. Something is seriously wrong!!";
+            break;
+    }
+}
+
+/**
+ *  Display all the submissions ready for grading
+ *
+ * @global object
+ * @global object
+ * @global object
+ * @global object
+ * @param string $message
+ * @return bool|void
+ */
+function lti_display_submissions($cm, $course, $basiclti, $message='') {
+    global $CFG, $DB, $OUTPUT, $PAGE;
+    require_once($CFG->libdir.'/gradelib.php');
+
+    /* first we check to see if the form has just been submitted
+     * to request user_preference updates
+     */
+    $updatepref = optional_param('updatepref', 0, PARAM_INT);
+
+    if (isset($_POST['updatepref'])) {
+        $perpage = optional_param('perpage', 10, PARAM_INT);
+        $perpage = ($perpage <= 0) ? 10 : $perpage;
+        $filter = optional_param('filter', 0, PARAM_INT);
+        set_user_preference('lti_perpage', $perpage);
+        set_user_preference('lti_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL));
+        set_user_preference('lti_filter', $filter);
+    }
+
+    /* next we get perpage and quickgrade (allow quick grade) params
+     * from database
+     */
+    $perpage    = get_user_preferences('lti_perpage', 10);
+    $quickgrade = get_user_preferences('lti_quickgrade', 0);
+    $filter = get_user_preferences('lti_filter', 0);
+    $grading_info = grade_get_grades($course->id, 'mod', 'lti', $basiclti->id);
+
+    if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) {
+        $uses_outcomes = true;
+    } else {
+        $uses_outcomes = false;
+    }
+
+    $page    = optional_param('page', 0, PARAM_INT);
+    $strsaveallfeedback = get_string('saveallfeedback', 'lti');
+
+    $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet
+    add_to_log($course->id, 'lti', 'view submission', 'submissions.php?id='.$cm->id, $basiclti->id, $cm->id);
+
+    $PAGE->set_title(format_string($basiclti->name, true));
+    $PAGE->set_heading($course->fullname);
+    echo $OUTPUT->header();
+
+    echo '<div class="usersubmissions">';
+
+    //hook to allow plagiarism plugins to update status/print links.
+    plagiarism_update_status($course, $cm);
+
+    /// Print quickgrade form around the table
+    if ($quickgrade) {
+        $formattrs = array();
+        $formattrs['action'] = new moodle_url('/mod/lti/submissions.php');
+        $formattrs['id'] = 'fastg';
+        $formattrs['method'] = 'post';
+
+        echo html_writer::start_tag('form', $formattrs);
+        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'id',      'value'=> $cm->id));
+        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'mode',    'value'=> 'fastgrade'));
+        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'page',    'value'=> $page));
+        echo html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'sesskey', 'value'=> sesskey()));
+    }
+
+    $course_context = get_context_instance(CONTEXT_COURSE, $course->id);
+    if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) {
+        echo '<div class="allcoursegrades"><a href="' . $CFG->wwwroot . '/grade/report/grader/index.php?id=' . $course->id . '">'
+            . get_string('seeallcoursegrades', 'grades') . '</a></div>';
+    }
+
+    if (!empty($message)) {
+        echo $message;   // display messages here if any
+    }
+
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+/// Check to see if groups are being used in this tool
+
+    /// find out current groups mode
+    $groupmode = groups_get_activity_groupmode($cm);
+    $currentgroup = groups_get_activity_group($cm, true);
+    groups_print_activity_menu($cm, $CFG->wwwroot . '/mod/lti/submissions.php?id=' . $cm->id);
+
+    /// Get all ppl that are allowed to submit tools
+    list($esql, $params) = get_enrolled_sql($context, 'mod/lti:view', $currentgroup);
+
+    $sql = "SELECT u.id FROM {user} u ".
+           "LEFT JOIN ($esql) eu ON eu.id=u.id ".
+           "WHERE u.deleted = 0 AND eu.id=u.id ";
+
+    $users = $DB->get_records_sql($sql, $params);
+    if (!empty($users)) {
+        $users = array_keys($users);
+    }
+
+    // if groupmembersonly used, remove users who are not in any group
+    if ($users and !empty($CFG->enablegroupmembersonly) and $cm->groupmembersonly) {
+        if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
+            $users = array_intersect($users, array_keys($groupingusers));
+        }
+    }
+
+    $tablecolumns = array('picture', 'fullname', 'grade', 'submissioncomment', 'timemodified', 'timemarked', 'status', 'finalgrade');
+    if ($uses_outcomes) {
+        $tablecolumns[] = 'outcome'; // no sorting based on outcomes column
+    }
+
+    $tableheaders = array('',
+                          get_string('fullname'),
+                          get_string('grade'),
+                          get_string('comment', 'lti'),
+                          get_string('lastmodified').' ('.get_string('submission', 'lti').')',
+                          get_string('lastmodified').' ('.get_string('grade').')',
+                          get_string('status'),
+                          get_string('finalgrade', 'grades'));
+    if ($uses_outcomes) {
+        $tableheaders[] = get_string('outcome', 'grades');
+    }
+
+    require_once($CFG->libdir.'/tablelib.php');
+    $table = new flexible_table('mod-lti-submissions');
+
+    $table->define_columns($tablecolumns);
+    $table->define_headers($tableheaders);
+    $table->define_baseurl($CFG->wwwroot.'/mod/lti/submissions.php?id='.$cm->id.'&amp;currentgroup='.$currentgroup);
+
+    $table->sortable(true, 'lastname');//sorted by lastname by default
+    $table->collapsible(true);
+    $table->initialbars(true);
+
+    $table->column_suppress('picture');
+    $table->column_suppress('fullname');
+
+    $table->column_class('picture', 'picture');
+    $table->column_class('fullname', 'fullname');
+    $table->column_class('grade', 'grade');
+    $table->column_class('submissioncomment', 'comment');
+    $table->column_class('timemodified', 'timemodified');
+    $table->column_class('timemarked', 'timemarked');
+    $table->column_class('status', 'status');
+    $table->column_class('finalgrade', 'finalgrade');
+    if ($uses_outcomes) {
+        $table->column_class('outcome', 'outcome');
+    }
+
+    $table->set_attribute('cellspacing', '0');
+    $table->set_attribute('id', 'attempts');
+    $table->set_attribute('class', 'submissions');
+    $table->set_attribute('width', '100%');
+
+    $table->no_sorting('finalgrade');
+    $table->no_sorting('outcome');
+
+    // Start working -- this is necessary as soon as the niceties are over
+    $table->setup();
+
+    if (empty($users)) {
+        echo $OUTPUT->heading(get_string('noviewusers', 'lti'));
+        echo '</div>';
+        return true;
+    }
+
+       /// Construct the SQL
+    list($where, $params) = $table->get_sql_where();
+    if ($where) {
+        $where .= ' AND ';
+    }
+
+    if ($sort = $table->get_sql_sort()) {
+        $sort = ' ORDER BY '.$sort;
+    }
+
+    $ufields = user_picture::fields('u');
+
+    $gradeitem = $DB->get_record('grade_items', array('courseid' => $cm->course, 'iteminstance' => $cm->instance));
+
+    $select = "SELECT $ufields,
+              g.rawgrade, g.feedback,
+              g.timemodified, g.timecreated ";
+
+    $sql = 'FROM {user} u'.
+            ' LEFT JOIN {grade_grades} g ON u.id = g.userid AND g.itemid = '.$gradeitem->id.
+            ' LEFT JOIN {grade_items} i ON g.itemid = i.id'.
+            ' AND i.iteminstance = '.$basiclti->id.
+            ' WHERE '.$where.'u.id IN ('.implode(',', $users).') ';
+
+    $ausers = $DB->get_records_sql($select.$sql.$sort, $params, $table->get_page_start(), $table->get_page_size());
+
+    $table->pagesize($perpage, count($users));
+
+    ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
+    $offset = $page * $perpage;
+    $strupdate = get_string('update');
+    $strgrade  = get_string('grade');
+    $grademenu = make_grades_menu($basiclti->grade);
+    if ($ausers !== false) {
+        $grading_info = grade_get_grades($course->id, 'mod', 'lti', $basiclti->id, array_keys($ausers));
+        $endposition = $offset + $perpage;
+        $currentposition = 0;
+        foreach ($ausers as $auser) {
+
+            if ($auser->timemodified > 0) {
+                $timemodified = '<div id="ts'.$auser->id.'">'.userdate($auser->timemodified).'</div>';
+            } else {
+                $timemodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
+            }
+            if ($auser->timecreated > 0) {
+                $timecreated = '<div id="ts'.$auser->id.'">'.userdate($auser->timecreated).'</div>';
+            } else {
+                $timecreated = '<div id="ts'.$auser->id.'">&nbsp;</div>';
+            }
+
+            if ($currentposition == $offset && $offset < $endposition) {
+                $final_grade = $grading_info->items[0]->grades[$auser->id];
+                $grademax = $grading_info->items[0]->grademax;
+                $final_grade->formatted_grade = round($final_grade->grade, 2) .' / ' . round($grademax, 2);
+                $locked_overridden = 'locked';
+                if ($final_grade->overridden) {
+                    $locked_overridden = 'overridden';
+                }
+
+                /// Calculate user status
+                $picture = $OUTPUT->user_picture($auser);
+
+                $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
+                $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
+                $status          = '<div id="st'.$auser->id.'">&nbsp;</div>';
+
+                if ($final_grade->locked or $final_grade->overridden) {
+                    $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade . '</div>';
+                } else if ($quickgrade) {   // allow editing
+                    $attributes = array();
+                    $attributes['tabindex'] = $tabindex++;
+                    if ($auser->rawgrade != "") {
+                        $menu = html_writer::select(make_grades_menu($basiclti->grade), 'menu['.$auser->id.']', round($auser->rawgrade, 0), array(-1=>get_string('nograde')), $attributes);
+                    } else {
+                        $menu = html_writer::select(make_grades_menu($basiclti->grade), 'menu['.$auser->id.']', -1, array(-1=>get_string('nograde')), $attributes);
+                    }
+                    $grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
+                } else if ($final_grade->grade) {
+                    if ($auser->rawgrade != "") {
+                        $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade.'</div>';
+                    } else {
+                        $grade = '<div id="g'.$auser->id.'">-1</div>';
+                    }
+
+                } else {
+                    $grade = '<div id="g'.$auser->id.'">No Grade</div>';
+                }
+
+                if ($final_grade->locked or $final_grade->overridden) {
+                    $comment = '<div id="com'.$auser->id.'">'.$final_grade->str_feedback.'</div>';
+                } else if ($quickgrade) {
+                    $comment = '<div id="com'.$auser->id.'">'
+                             . '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
+                             . $auser->id.'" rows="2" cols="20">'.($auser->feedback).'</textarea></div>';
+                } else {
+                    $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->feedback), 15).'</div>';
+                }
+
+                if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1
+                    $auser->status = 0;
+                } else {
+                    $auser->status = 1;
+                }
+
+                $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
+
+                ///No more buttons, we use popups ;-).
+                $popup_url = '/mod/lti/submissions.php?id='.$cm->id
+                           . '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;filter='.$filter.'&amp;offset='.$offset++;
+
+                $button = $OUTPUT->action_link($popup_url, $buttontext);
+
+                $status  = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
+
+                $finalgrade = '<span id="finalgrade_'.$auser->id.'">'.$final_grade->str_grade.'</span>';
+
+                $outcomes = '';
+
+                if ($uses_outcomes) {
+
+                    foreach ($grading_info->outcomes as $n => $outcome) {
+                        $outcomes .= '<div class="outcome"><label>'.$outcome->name.'</label>';
+                        $options = make_grades_menu(-$outcome->scaleid);
+
+                        if ($outcome->grades[$auser->id]->locked or !$quickgrade) {
+                            $options[0] = get_string('nooutcome', 'grades');
+                            $outcomes .= ': <span id="outcome_'.$n.'_'.$auser->id.'">'.$options[$outcome->grades[$auser->id]->grade].'</span>';
+                        } else {
+                            $attributes = array();
+                            $attributes['tabindex'] = $tabindex++;
+                            $attributes['id'] = 'outcome_'.$n.'_'.$auser->id;
+                            $outcomes .= ' '.html_writer::select($options, 'outcome_'.$n.'['.$auser->id.']', $outcome->grades[$auser->id]->grade, array(0=>get_string('nooutcome', 'grades')), $attributes);
+                        }
+                        $outcomes .= '</div>';
+                    }
+                }
+
+                $userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser, has_capability('moodle/site:viewfullnames', $context)) . '</a>';
+                $row = array($picture, $userlink, $grade, $comment, $timemodified, $timecreated, $status, $finalgrade);
+                if ($uses_outcomes) {
+                    $row[] = $outcomes;
+                }
+
+                $table->add_data($row);
+            }
+            $currentposition++;
+        }
+    }
+
+    $table->print_html();  /// Print the whole table
+
+    /// Print quickgrade form around the table
+    if ($quickgrade && $table->started_output) {
+        $mailinfopref = false;
+        if (get_user_preferences('lti_mailinfo', 1)) {
+            $mailinfopref = true;
+        }
+        $emailnotification =  html_writer::checkbox('mailinfo', 1, $mailinfopref, get_string('enableemailnotification', 'lti'));
+
+        $emailnotification .= $OUTPUT->help_icon('enableemailnotification', 'lti');
+        echo html_writer::tag('div', $emailnotification, array('class'=>'emailnotification'));
+
+        $savefeedback = html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'fastg', 'value'=>get_string('saveallfeedback', 'lti')));
+        echo html_writer::tag('div', $savefeedback, array('class'=>'fastgbutton'));
+
+        echo html_writer::end_tag('form');
+    } else if ($quickgrade) {
+        echo html_writer::end_tag('form');
+    }
+
+    echo '</div>';
+    /// End of fast grading form
+
+    /// Mini form for setting user preference
+
+    $formaction = new moodle_url('/mod/lti/submissions.php', array('id'=>$cm->id));
+    $mform = new MoodleQuickForm('optionspref', 'post', $formaction, '', array('class'=>'optionspref'));
+
+    $mform->addElement('hidden', 'updatepref');
+    $mform->setDefault('updatepref', 1);
+    $mform->addElement('header', 'qgprefs', get_string('optionalsettings', 'lti'));
+//        $mform->addElement('select', 'filter', get_string('show'),  $filters);
+
+    $mform->setDefault('filter', $filter);
+
+    $mform->addElement('text', 'perpage', get_string('pagesize', 'lti'), array('size'=>1));
+    $mform->setDefault('perpage', $perpage);
+
+    $mform->addElement('checkbox', 'quickgrade', get_string('quickgrade', 'lti'));
+    $mform->setDefault('quickgrade', $quickgrade);
+    $mform->addHelpButton('quickgrade', 'quickgrade', 'lti');
+
+    $mform->addElement('submit', 'savepreferences', get_string('savepreferences'));
+
+    $mform->display();
+
+    echo $OUTPUT->footer();
+}
+
+/**
+ * Create grade item for given basiclti
+ *
+ * @param object $basiclti object with extra cmidnumber
+ * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook
+ * @return int 0 if ok, error code otherwise
+ */
+function lti_grade_item_update($basiclti, $grades=null) {
+    global $CFG;
+    require_once($CFG->libdir.'/gradelib.php');
+
+    $params = array('itemname'=>$basiclti->name, 'idnumber'=>$basiclti->cmidnumber);
+
+    if ($basiclti->grade > 0) {
+        $params['gradetype'] = GRADE_TYPE_VALUE;
+        $params['grademax']  = $basiclti->grade;
+        $params['grademin']  = 0;
+
+    } else if ($basiclti->grade < 0) {
+        $params['gradetype'] = GRADE_TYPE_SCALE;
+        $params['scaleid']   = -$basiclti->grade;
+
+    } else {
+        $params['gradetype'] = GRADE_TYPE_TEXT; // allow text comments only
+    }
+
+    if ($grades  === 'reset') {
+        $params['reset'] = true;
+        $grades = null;
+    }
+
+    return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, $grades, $params);
+}
+
+/**
+ * Delete grade item for given basiclti
+ *
+ * @param object $basiclti object
+ * @return object basiclti
+ */
+function lti_grade_item_delete($basiclti) {
+    global $CFG;
+    require_once($CFG->libdir.'/gradelib.php');
+
+    return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, null, array('deleted'=>1));
+}
+