Пример #1
0
 /**
  * Update completion status for the current user in an activity, only for activities with manual tracking.
  * @param  int $cmid      Course module id
  * @param  bool $completed Activity completed or not
  * @return array            Result and possible warnings
  * @since Moodle 2.9
  * @throws moodle_exception
  */
 public static function update_activity_completion_status_manually($cmid, $completed)
 {
     // Validate and normalize parameters.
     $params = self::validate_parameters(self::update_activity_completion_status_manually_parameters(), array('cmid' => $cmid, 'completed' => $completed));
     $cmid = $params['cmid'];
     $completed = $params['completed'];
     $warnings = array();
     $context = context_module::instance($cmid);
     self::validate_context($context);
     list($course, $cm) = get_course_and_cm_from_cmid($cmid);
     // Set up completion object and check it is enabled.
     $completion = new completion_info($course);
     if (!$completion->is_enabled()) {
         throw new moodle_exception('completionnotenabled', 'completion');
     }
     // Check completion state is manual.
     if ($cm->completion != COMPLETION_TRACKING_MANUAL) {
         throw new moodle_exception('cannotmanualctrack', 'error');
     }
     $targetstate = $completed ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE;
     $completion->update_state($cm, $targetstate);
     $result = array();
     $result['status'] = true;
     $result['warnings'] = $warnings;
     return $result;
 }
 public function execute()
 {
     global $DB, $CFG;
     $result = $DB->get_records_sql('SELECT ba.id, ba.bookingid, ba.optionid, ba.userid, b.course
         FROM {booking_answers} AS ba
         LEFT JOIN {booking_options} AS bo 
         ON bo.id = ba.optionid
         LEFT JOIN {booking} AS b
         ON b.id = bo.bookingid
         WHERE bo.removeafterminutes > 0
         AND ba.completed = 1
         AND IF(ba.timemodified < (UNIX_TIMESTAMP() - (bo.removeafterminutes*60)), 1, 0) = 1;');
     require_once $CFG->libdir . '/completionlib.php';
     foreach ($result as $value) {
         $course = $DB->get_record('course', array('id' => $value->course));
         $completion = new \completion_info($course);
         $cm = get_coursemodule_from_instance('booking', $value->bookingid);
         $userData = $DB->get_record('booking_answers', array('id' => $value->id));
         $booking = $DB->get_record('booking', array('id' => $value->bookingid));
         $userData->completed = '0';
         $userData->timemodified = time();
         $DB->update_record('booking_answers', $userData);
         if ($completion->is_enabled($cm) && $booking->enablecompletion) {
             $completion->update_state($cm, COMPLETION_INCOMPLETE, $userData->userid);
         }
     }
 }
/**
 *
 * @param cm_info $cm
 * @param stdClass $stopwatch
 * @param int $duration
 */
function mod_stopwatch_update_timer(cm_info $cm, $stopwatch, $duration)
{
    global $USER, $DB, $CFG;
    require_once $CFG->libdir . '/completionlib.php';
    $record = $DB->get_record('stopwatch_user', array('stopwatchid' => $cm->instance, 'courseid' => $cm->course, 'userid' => $USER->id));
    if ($record) {
        $data = array('id' => $record->id, 'timemodified' => time(), 'duration' => $duration);
        $DB->update_record('stopwatch_user', $data);
    } else {
        $data = array('courseid' => $cm->course, 'stopwatchid' => $cm->instance, 'userid' => $USER->id, 'timecreated' => time(), 'timemodified' => time(), 'duration' => $duration);
        $DB->insert_record('stopwatch_user', $data);
    }
    // Update completion state
    $completion = new completion_info($cm->get_course());
    if ($completion->is_enabled($cm) && $stopwatch->completiontimed) {
        $completion->update_state($cm, COMPLETION_COMPLETE);
    }
}
Пример #4
0
 /**
  * Updates activity completion status.
  *
  * @return void
  */
 public static function update_require_specific_grade(\core\event\base $event)
 {
     global $DB;
     $entryuserid = $event->relateduserid;
     $giid = $event->other['itemid'];
     if (!($gitem = \grade_item::fetch(array('id' => $giid, 'itemmodule' => 'dataform')))) {
         return;
     }
     $dataformid = $gitem->iteminstance;
     $df = \mod_dataform_dataform::instance($dataformid);
     // Currently only completion by require entries.
     if ($df->completionspecificgrade) {
         $completion = new \completion_info($df->course);
         if ($completion->is_enabled($df->cm) != COMPLETION_TRACKING_AUTOMATIC) {
             return;
         }
         $completion->update_state($df->cm, COMPLETION_UNKNOWN, $entryuserid);
     }
 }
Пример #5
0
function checklist_update_grades($checklist, $userid = 0)
{
    global $CFG, $DB;
    $items = $DB->get_records('checklist_item', array('checklist' => $checklist->id, 'userid' => 0, 'itemoptional' => CHECKLIST_OPTIONAL_NO, 'hidden' => CHECKLIST_HIDDEN_NO), '', 'id, grouping');
    if (!$items) {
        return;
    }
    if (!($course = $DB->get_record('course', array('id' => $checklist->course)))) {
        return;
    }
    if (!($cm = get_coursemodule_from_instance('checklist', $checklist->id, $course->id))) {
        return;
    }
    $checkgroupings = false;
    // Don't check items against groupings unless we really have to
    if (isset($CFG->enablegroupmembersonly) && $CFG->enablegroupmembersonly && $checklist->autopopulate) {
        foreach ($items as $item) {
            if ($item->grouping) {
                $checkgroupings = true;
                break;
            }
        }
    }
    if ($checklist->teacheredit == CHECKLIST_MARKING_STUDENT) {
        $date = ', MAX(c.usertimestamp) AS datesubmitted';
        $where = 'c.usertimestamp > 0';
    } else {
        $date = ', MAX(c.teachertimestamp) AS dategraded';
        $where = 'c.teachermark = ' . CHECKLIST_TEACHERMARK_YES;
    }
    if ($checkgroupings) {
        if ($userid) {
            $users = $DB->get_records('user', array('id' => $userid), null, 'id, firstname, lastname');
        } else {
            if ($CFG->version < 2011120100) {
                $context = get_context_instance(CONTEXT_MODULE, $cm->id);
            } else {
                $context = context_module::instance($cm->id);
            }
            if (!($users = get_users_by_capability($context, 'mod/checklist:updateown', 'u.id, u.firstname, u.lastname', '', '', '', '', '', false))) {
                return;
            }
        }
        $grades = array();
        // With groupings, need to update each user individually (as each has different groupings)
        foreach ($users as $userid => $user) {
            $groupings = checklist_class::get_user_groupings($userid, $course->id);
            $total = 0;
            $itemlist = '';
            foreach ($items as $item) {
                if ($item->grouping) {
                    if (!in_array($item->grouping, $groupings)) {
                        continue;
                    }
                }
                $itemlist .= $item->id . ',';
                $total++;
            }
            if (!$total) {
                // No items - set score to 0
                $ugrade = new stdClass();
                $ugrade->userid = $userid;
                $ugrade->rawgrade = 0;
                $ugrade->date = time();
            } else {
                $itemlist = substr($itemlist, 0, -1);
                // Remove trailing ','
                $sql = 'SELECT ? AS userid, (SUM(CASE WHEN ' . $where . ' THEN 1 ELSE 0 END) * ? / ? ) AS rawgrade' . $date;
                $sql .= " FROM {checklist_check} c ";
                $sql .= " WHERE c.item IN ({$itemlist})";
                $sql .= ' AND c.userid = ? ';
                $ugrade = $DB->get_record_sql($sql, array($userid, $checklist->maxgrade, $total, $userid));
                if (!$ugrade) {
                    $ugrade = new stdClass();
                    $ugrade->userid = $userid;
                    $ugrade->rawgrade = 0;
                    $ugrade->date = time();
                }
            }
            $ugrade->firstname = $user->firstname;
            $ugrade->lastname = $user->lastname;
            $grades[$userid] = $ugrade;
        }
    } else {
        // No need to check groupings, so update all student grades at once
        if ($userid) {
            $users = $userid;
        } else {
            if ($CFG->version < 2011120100) {
                $context = get_context_instance(CONTEXT_MODULE, $cm->id);
            } else {
                $context = context_module::instance($cm->id);
            }
            if (!($users = get_users_by_capability($context, 'mod/checklist:updateown', 'u.id', '', '', '', '', '', false))) {
                return;
            }
            $users = array_keys($users);
        }
        $total = count($items);
        list($usql, $uparams) = $DB->get_in_or_equal($users);
        list($isql, $iparams) = $DB->get_in_or_equal(array_keys($items));
        $sql = 'SELECT u.id AS userid, (SUM(CASE WHEN ' . $where . ' THEN 1 ELSE 0 END) * ? / ? ) AS rawgrade' . $date;
        $sql .= ' , u.firstname, u.lastname ';
        $sql .= ' FROM {user} u LEFT JOIN {checklist_check} c ON u.id = c.userid';
        $sql .= " WHERE u.id {$usql}";
        $sql .= " AND c.item {$isql}";
        $sql .= ' GROUP BY u.id, u.firstname, u.lastname';
        $params = array_merge($uparams, $iparams);
        $params = array_merge(array($checklist->maxgrade, $total), $params);
        $grades = $DB->get_records_sql($sql, $params);
    }
    foreach ($grades as $grade) {
        // Log completion of checklist
        if ($grade->rawgrade == $checklist->maxgrade) {
            if ($checklist->emailoncomplete) {
                $timelimit = time() - 1 * 60 * 60;
                // Do not send another email if this checklist was already 'completed' in the last hour
                $filter = "l.time > ? AND l.cmid = ? AND l.userid = ? AND l.action = 'complete'";
                get_logs($filter, array($timelimit, $cm->id, $grade->userid), '', 1, 1, $logcount);
                if ($logcount == 0) {
                    if (!isset($context)) {
                        if ($CFG->version < 2011120100) {
                            $context = get_context_instance(CONTEXT_MODULE, $cm->id);
                        } else {
                            $context = context_module::instance($cm->id);
                        }
                    }
                    if ($recipients = get_users_by_capability($context, 'mod/checklist:emailoncomplete', 'u.*', '', '', '', '', '', false)) {
                        foreach ($recipients as $recipient) {
                            $details = new stdClass();
                            $details->user = fullname($grade);
                            $details->checklist = s($checklist->name);
                            $subj = get_string('emailoncompletesubject', 'checklist', $details);
                            $content = get_string('emailoncompletebody', 'checklist', $details);
                            $content .= $CFG->wwwroot . '/mod/checklist/view.php?id=' . $cm->id;
                            email_to_user($recipient, $grade, $subj, $content, '', '', '', false);
                        }
                    }
                }
            }
            add_to_log($checklist->course, 'checklist', 'complete', "view.php?id={$cm->id}", $checklist->name, $cm->id, $grade->userid);
        }
        $ci = new completion_info($course);
        if ($cm->completion == COMPLETION_TRACKING_AUTOMATIC) {
            $ci->update_state($cm, COMPLETION_UNKNOWN, $grade->userid);
        }
    }
    checklist_grade_item_update($checklist, $grades);
}
Пример #6
0
require_course_login($course, false, $cm);
if (!($choice = choice_get_choice($cm->instance))) {
    print_error('invalidcoursemodule');
}
$strchoice = get_string('modulename', 'choice');
$strchoices = get_string('modulenameplural', 'choice');
$context = context_module::instance($cm->id);
list($choiceavailable, $warnings) = choice_get_availability_status($choice);
if ($action == 'delchoice' and confirm_sesskey() and is_enrolled($context, NULL, 'mod/choice:choose') and $choice->allowupdate and $choiceavailable) {
    $answercount = $DB->count_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $USER->id));
    if ($answercount > 0) {
        $DB->delete_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $USER->id));
        // Update completion state
        $completion = new completion_info($course);
        if ($completion->is_enabled($cm) && $choice->completionsubmit) {
            $completion->update_state($cm, COMPLETION_INCOMPLETE);
        }
        redirect("view.php?id={$cm->id}");
    }
}
$PAGE->set_title($choice->name);
$PAGE->set_heading($course->fullname);
/// Submit any new data if there is any
if (data_submitted() && is_enrolled($context, NULL, 'mod/choice:choose') && confirm_sesskey()) {
    $timenow = time();
    if (has_capability('mod/choice:deleteresponses', $context) && $action == 'delete') {
        //some responses need to be deleted
        choice_delete_responses($attemptids, $choice, $cm, $course);
        //delete responses.
        redirect("view.php?id={$cm->id}");
    }
Пример #7
0
$context = context_module::instance($cm->id);
require_capability('mod/glossary:approve', $context);
if ($newstate != $entry->approved && confirm_sesskey()) {
    $newentry = new stdClass();
    $newentry->id = $entry->id;
    $newentry->approved = $newstate;
    $newentry->timemodified = time();
    // wee need this date here to speed up recent activity, TODO: use timestamp in approved field instead in 2.0
    $DB->update_record("glossary_entries", $newentry);
    // Trigger event about entry approval/disapproval.
    $params = array('context' => $context, 'objectid' => $entry->id);
    if ($newstate) {
        $event = \mod_glossary\event\entry_approved::create($params);
    } else {
        $event = \mod_glossary\event\entry_disapproved::create($params);
    }
    $entry->approved = $newstate ? 1 : 0;
    $entry->timemodified = $newentry->timemodified;
    $event->add_record_snapshot('glossary_entries', $entry);
    $event->trigger();
    // Update completion state
    $completion = new completion_info($course);
    if ($completion->is_enabled($cm) == COMPLETION_TRACKING_AUTOMATIC && $glossary->completionentries) {
        $completion->update_state($cm, COMPLETION_COMPLETE, $entry->userid);
    }
    // Reset caches.
    if ($entry->usedynalink) {
        \mod_glossary\local\concept_cache::reset_glossary($glossary);
    }
}
redirect("view.php?id={$cm->id}&amp;mode={$mode}&amp;hook={$hook}");
Пример #8
0
/**
 * Removes grades and resets completion
 *
 * @global object $CFG
 * @global object $DB
 * @param int $userid
 * @param int $courseid
 * @return boolean
 */
function facetoface_archive_completion($userid, $courseid) {
    global $DB, $CFG;

    require_once($CFG->libdir . '/completionlib.php');

    $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
    $completion = new completion_info($course);

    // All face to face with this course and user
    $sql = "SELECT f.*
            FROM {facetoface} f
            WHERE f.course = :courseid
            AND EXISTS (SELECT su.id
                        FROM {facetoface_sessions} s
                        JOIN {facetoface_signups} su ON su.sessionid = s.id AND su.userid = :userid
                        WHERE s.facetoface = f.id)";
    $facetofaces = $DB->get_records_sql($sql, array('courseid' => $courseid, 'userid' => $userid));
    foreach ($facetofaces as $facetoface) {
        // Add an archive flag
        $params = array('facetofaceid' => $facetoface->id, 'userid' => $userid, 'archived' => 1, 'archived2' => 1);
        $sql = "UPDATE {facetoface_signups}
                SET archived = :archived
                WHERE userid = :userid
                AND archived <> :archived2
                AND EXISTS (SELECT {facetoface_sessions}.id
                            FROM {facetoface_sessions}
                            WHERE {facetoface_sessions}.id = {facetoface_signups}.sessionid
                            AND {facetoface_sessions}.facetoface = :facetofaceid)";
        $DB->execute($sql, $params);

        // Reset the grades
        facetoface_update_grades($facetoface, $userid, true);

        // Set completion to incomplete
        // Reset viewed
        $course_module = get_coursemodule_from_instance('facetoface', $facetoface->id, $courseid);
        $completion->set_module_viewed_reset($course_module, $userid);
        // And reset completion, in case viewed is not a required condition
        $completion->update_state($course_module, COMPLETION_INCOMPLETE, $userid);
        $completion->invalidatecache($courseid, $userid, true);
    }
}
Пример #9
0
/**
 * Deletes a single forum post.
 *
 * @global object
 * @param object $post Forum post object
 * @param mixed $children Whether to delete children. If false, returns false
 *   if there are any children (without deleting the post). If true,
 *   recursively deletes all children. If set to special value 'ignore', deletes
 *   post regardless of children (this is for use only when deleting all posts
 *   in a disussion).
 * @param object $course Course
 * @param object $cm Course-module
 * @param object $forum Forum
 * @param bool $skipcompletion True to skip updating completion state if it
 *   would otherwise be updated, i.e. when deleting entire forum anyway.
 * @return bool
 */
function forum_delete_post($post, $children, $course, $cm, $forum, $skipcompletion = false)
{
    global $DB, $CFG, $USER;
    require_once $CFG->libdir . '/completionlib.php';
    $context = context_module::instance($cm->id);
    if ($children !== 'ignore' && ($childposts = $DB->get_records('forum_posts', array('parent' => $post->id)))) {
        if ($children) {
            foreach ($childposts as $childpost) {
                forum_delete_post($childpost, true, $course, $cm, $forum, $skipcompletion);
            }
        } else {
            return false;
        }
    }
    // Delete ratings.
    require_once $CFG->dirroot . '/rating/lib.php';
    $delopt = new stdClass();
    $delopt->contextid = $context->id;
    $delopt->component = 'mod_forum';
    $delopt->ratingarea = 'post';
    $delopt->itemid = $post->id;
    $rm = new rating_manager();
    $rm->delete_ratings($delopt);
    // Delete attachments.
    $fs = get_file_storage();
    $fs->delete_area_files($context->id, 'mod_forum', 'attachment', $post->id);
    $fs->delete_area_files($context->id, 'mod_forum', 'post', $post->id);
    // Delete cached RSS feeds.
    if (!empty($CFG->enablerssfeeds)) {
        require_once $CFG->dirroot . '/mod/forum/rsslib.php';
        forum_rss_delete_file($forum);
    }
    if ($DB->delete_records("forum_posts", array("id" => $post->id))) {
        forum_tp_delete_read_records(-1, $post->id);
        // Just in case we are deleting the last post
        forum_discussion_update_last_post($post->discussion);
        // Update completion state if we are tracking completion based on number of posts
        // But don't bother when deleting whole thing
        if (!$skipcompletion) {
            $completion = new completion_info($course);
            if ($completion->is_enabled($cm) == COMPLETION_TRACKING_AUTOMATIC && ($forum->completiondiscussions || $forum->completionreplies || $forum->completionposts)) {
                $completion->update_state($cm, COMPLETION_INCOMPLETE, $post->userid);
            }
        }
        $params = array('context' => $context, 'objectid' => $post->id, 'other' => array('discussionid' => $post->discussion, 'forumid' => $forum->id, 'forumtype' => $forum->type));
        if ($post->userid !== $USER->id) {
            $params['relateduserid'] = $post->userid;
        }
        $event = \mod_forum\event\post_deleted::create($params);
        $event->add_record_snapshot('forum_posts', $post);
        $event->trigger();
        return true;
    }
    return false;
}
Пример #10
0
    /**
     * Add a new discussion into an existing forum.
     *
     * @param int $forumid the forum instance id
     * @param string $subject new discussion subject
     * @param string $message new discussion message (only html format allowed)
     * @param int $groupid the user course group
     * @param array $options optional settings
     * @return array of warnings and the new discussion id
     * @since Moodle 3.0
     * @throws moodle_exception
     */
    public static function add_discussion($forumid, $subject, $message, $groupid = -1, $options = array()) {
        global $DB, $CFG;
        require_once($CFG->dirroot . "/mod/forum/lib.php");

        $params = self::validate_parameters(self::add_discussion_parameters(),
                                            array(
                                                'forumid' => $forumid,
                                                'subject' => $subject,
                                                'message' => $message,
                                                'groupid' => $groupid,
                                                'options' => $options
                                            ));
        // Validate options.
        $options = array(
            'discussionsubscribe' => true
        );
        foreach ($params['options'] as $option) {
            $name = trim($option['name']);
            switch ($name) {
                case 'discussionsubscribe':
                    $value = clean_param($option['value'], PARAM_BOOL);
                    break;
                default:
                    throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
            }
            $options[$name] = $value;
        }

        $warnings = array();

        // Request and permission validation.
        $forum = $DB->get_record('forum', array('id' => $params['forumid']), '*', MUST_EXIST);
        list($course, $cm) = get_course_and_cm_from_instance($forum, 'forum');

        $context = context_module::instance($cm->id);
        self::validate_context($context);

        // Normalize group.
        if (!groups_get_activity_groupmode($cm)) {
            // Groups not supported, force to -1.
            $groupid = -1;
        } else {
            // Check if we receive the default or and empty value for groupid,
            // in this case, get the group for the user in the activity.
            if ($groupid === -1 or empty($params['groupid'])) {
                $groupid = groups_get_activity_group($cm);
            } else {
                // Here we rely in the group passed, forum_user_can_post_discussion will validate the group.
                $groupid = $params['groupid'];
            }
        }

        if (!forum_user_can_post_discussion($forum, $groupid, -1, $cm, $context)) {
            throw new moodle_exception('cannotcreatediscussion', 'forum');
        }

        $thresholdwarning = forum_check_throttling($forum, $cm);
        forum_check_blocking_threshold($thresholdwarning);

        // Create the discussion.
        $discussion = new stdClass();
        $discussion->course = $course->id;
        $discussion->forum = $forum->id;
        $discussion->message = $params['message'];
        $discussion->messageformat = FORMAT_HTML;   // Force formatting for now.
        $discussion->messagetrust = trusttext_trusted($context);
        $discussion->itemid = 0;
        $discussion->groupid = $groupid;
        $discussion->mailnow = 0;
        $discussion->subject = $params['subject'];
        $discussion->name = $discussion->subject;
        $discussion->timestart = 0;
        $discussion->timeend = 0;

        if ($discussionid = forum_add_discussion($discussion)) {

            $discussion->id = $discussionid;

            // Trigger events and completion.

            $params = array(
                'context' => $context,
                'objectid' => $discussion->id,
                'other' => array(
                    'forumid' => $forum->id,
                )
            );
            $event = \mod_forum\event\discussion_created::create($params);
            $event->add_record_snapshot('forum_discussions', $discussion);
            $event->trigger();

            $completion = new completion_info($course);
            if ($completion->is_enabled($cm) &&
                    ($forum->completiondiscussions || $forum->completionposts)) {
                $completion->update_state($cm, COMPLETION_COMPLETE);
            }

            $settings = new stdClass();
            $settings->discussionsubscribe = $options['discussionsubscribe'];
            forum_post_subscription($settings, $forum, $discussion);
        } else {
            throw new moodle_exception('couldnotadd', 'forum');
        }

        $result = array();
        $result['discussionid'] = $discussionid;
        $result['warnings'] = $warnings;
        return $result;
    }
Пример #11
0
/**
 * Creates or updates a glossary entry
 *
 * @param  stdClass $entry entry data
 * @param  stdClass $course course object
 * @param  stdClass $cm course module object
 * @param  stdClass $glossary glossary object
 * @param  stdClass $context context object
 * @return stdClass the complete new or updated entry
 * @since  Moodle 3.2
 */
function glossary_edit_entry($entry, $course, $cm, $glossary, $context) {
    global $DB, $USER;

    list($definitionoptions, $attachmentoptions) = glossary_get_editor_and_attachment_options($course, $context, $entry);

    $timenow = time();

    $categories = empty($entry->categories) ? array() : $entry->categories;
    unset($entry->categories);
    $aliases = trim($entry->aliases);
    unset($entry->aliases);

    if (empty($entry->id)) {
        $entry->glossaryid       = $glossary->id;
        $entry->timecreated      = $timenow;
        $entry->userid           = $USER->id;
        $entry->timecreated      = $timenow;
        $entry->sourceglossaryid = 0;
        $entry->teacherentry     = has_capability('mod/glossary:manageentries', $context);
        $isnewentry              = true;
    } else {
        $isnewentry              = false;
    }

    $entry->concept          = trim($entry->concept);
    $entry->definition       = '';          // Updated later.
    $entry->definitionformat = FORMAT_HTML; // Updated later.
    $entry->definitiontrust  = 0;           // Updated later.
    $entry->timemodified     = $timenow;
    $entry->approved         = 0;
    $entry->usedynalink      = isset($entry->usedynalink) ? $entry->usedynalink : 0;
    $entry->casesensitive    = isset($entry->casesensitive) ? $entry->casesensitive : 0;
    $entry->fullmatch        = isset($entry->fullmatch) ? $entry->fullmatch : 0;

    if ($glossary->defaultapproval or has_capability('mod/glossary:approve', $context)) {
        $entry->approved = 1;
    }

    if ($isnewentry) {
        // Add new entry.
        $entry->id = $DB->insert_record('glossary_entries', $entry);
    } else {
        // Update existing entry.
        $DB->update_record('glossary_entries', $entry);
    }

    // Save and relink embedded images and save attachments.
    if (!empty($entry->definition_editor)) {
        $entry = file_postupdate_standard_editor($entry, 'definition', $definitionoptions, $context, 'mod_glossary', 'entry',
            $entry->id);
    }
    if (!empty($entry->attachment_filemanager)) {
        $entry = file_postupdate_standard_filemanager($entry, 'attachment', $attachmentoptions, $context, 'mod_glossary',
            'attachment', $entry->id);
    }

    // Store the updated value values.
    $DB->update_record('glossary_entries', $entry);

    // Refetch complete entry.
    $entry = $DB->get_record('glossary_entries', array('id' => $entry->id));

    // Update entry categories.
    $DB->delete_records('glossary_entries_categories', array('entryid' => $entry->id));
    // TODO: this deletes cats from both both main and secondary glossary :-(.
    if (!empty($categories) and array_search(0, $categories) === false) {
        foreach ($categories as $catid) {
            $newcategory = new stdClass();
            $newcategory->entryid    = $entry->id;
            $newcategory->categoryid = $catid;
            $DB->insert_record('glossary_entries_categories', $newcategory, false);
        }
    }

    // Update aliases.
    $DB->delete_records('glossary_alias', array('entryid' => $entry->id));
    if ($aliases !== '') {
        $aliases = explode("\n", $aliases);
        foreach ($aliases as $alias) {
            $alias = trim($alias);
            if ($alias !== '') {
                $newalias = new stdClass();
                $newalias->entryid = $entry->id;
                $newalias->alias   = $alias;
                $DB->insert_record('glossary_alias', $newalias, false);
            }
        }
    }

    // Trigger event and update completion (if entry was created).
    $eventparams = array(
        'context' => $context,
        'objectid' => $entry->id,
        'other' => array('concept' => $entry->concept)
    );
    if ($isnewentry) {
        $event = \mod_glossary\event\entry_created::create($eventparams);
    } else {
        $event = \mod_glossary\event\entry_updated::create($eventparams);
    }
    $event->add_record_snapshot('glossary_entries', $entry);
    $event->trigger();
    if ($isnewentry) {
        // Update completion state.
        $completion = new completion_info($course);
        if ($completion->is_enabled($cm) == COMPLETION_TRACKING_AUTOMATIC && $glossary->completionentries && $entry->approved) {
            $completion->update_state($cm, COMPLETION_COMPLETE);
        }
    }

    // Reset caches.
    if ($isnewentry) {
        if ($entry->usedynalink and $entry->approved) {
            \mod_glossary\local\concept_cache::reset_glossary($glossary);
        }
    } else {
        // So many things may affect the linking, let's just purge the cache always on edit.
        \mod_glossary\local\concept_cache::reset_glossary($glossary);
    }
    return $entry;
}
Пример #12
0
function booking_activitycompletion($selectedusers, $booking, $cmid, $optionid)
{
    global $DB;
    $course = $DB->get_record('course', array('id' => $booking->course));
    $completion = new completion_info($course);
    $cm = get_coursemodule_from_id('booking', $cmid, 0, false, MUST_EXIST);
    foreach ($selectedusers as $ui) {
        $userData = $DB->get_record('booking_answers', array('optionid' => $optionid, 'userid' => $ui));
        if ($userData->completed == '1') {
            $userData->completed = '0';
            $userData->timemodified = time();
            $DB->update_record('booking_answers', $userData);
            if ($completion->is_enabled($cm) && $booking->enablecompletion) {
                $completion->update_state($cm, COMPLETION_INCOMPLETE, $ui);
            }
        } else {
            $userData->completed = '1';
            $userData->timemodified = time();
            $DB->update_record('booking_answers', $userData);
            if ($completion->is_enabled($cm) && $booking->enablecompletion) {
                $completion->update_state($cm, COMPLETION_COMPLETE, $ui);
            }
        }
    }
}
 /**
  * Verify if user meet issue conditions
  * 
  * @param int $userid User id
  * @return string null if user meet issued conditions, or an text with erro
  */
 protected function can_issue($user = null, $chkcompletation = true)
 {
     global $DB, $USER, $CFG;
     if (empty($user)) {
         $user = $USER;
     }
     if (has_capability('mod/simplecertificate:manage', $this->context, $user)) {
         return get_string('cantissue', 'simplecertificate');
     }
     if ($chkcompletation) {
         $completion = new completion_info($this->course);
         if ($completion->is_enabled($this->coursemodule) && $this->get_instance()->requiredtime) {
             if ($this->get_course_time($user) < $this->get_instance()->requiredtime) {
                 $a = new stdClass();
                 $a->requiredtime = $this->get_instance()->requiredtime;
                 return get_string('requiredtimenotmet', 'simplecertificate', $a);
             }
             // Mark as complete
             $completion->update_state($this->coursemodule, COMPLETION_COMPLETE, $user->id);
         }
         if ($CFG->enableavailability) {
             $modinfo = get_fast_modinfo($this->get_course());
             $cm = $modinfo->get_cm($this->get_course_module()->id);
             if (!$cm->uservisible) {
                 if ($cm->availableinfo) {
                     return $cm->availableinfo;
                 } else {
                     return get_string('cantissue', 'simplecertificate');
                 }
             }
             return null;
         }
     }
 }
Пример #14
0
 /**
  * Updates the timer to the current time and returns the new timer object
  * @param bool $restart If set to true the timer is restarted
  * @param bool $continue If set to true AND $restart=true then the timer
  *                        will continue from a previous attempt
  * @return stdClass The new timer
  */
 public function update_timer($restart = false, $continue = false, $endreached = false)
 {
     global $USER, $DB;
     $cm = get_coursemodule_from_instance('lesson', $this->properties->id, $this->properties->course);
     // clock code
     // get time information for this user
     $params = array("lessonid" => $this->properties->id, "userid" => $USER->id);
     if (!($timer = $DB->get_records('lesson_timer', $params, 'starttime DESC', '*', 0, 1))) {
         $this->start_timer();
         $timer = $DB->get_records('lesson_timer', $params, 'starttime DESC', '*', 0, 1);
     }
     $timer = current($timer);
     // This will get the latest start time record.
     if ($restart) {
         if ($continue) {
             // continue a previous test, need to update the clock  (think this option is disabled atm)
             $timer->starttime = time() - ($timer->lessontime - $timer->starttime);
             // Trigger lesson resumed event.
             $event = \mod_lesson\event\lesson_resumed::create(array('objectid' => $this->properties->id, 'context' => context_module::instance($cm->id), 'courseid' => $this->properties->course));
             $event->trigger();
         } else {
             // starting over, so reset the clock
             $timer->starttime = time();
             // Trigger lesson restarted event.
             $event = \mod_lesson\event\lesson_restarted::create(array('objectid' => $this->properties->id, 'context' => context_module::instance($cm->id), 'courseid' => $this->properties->course));
             $event->trigger();
         }
     }
     $timer->lessontime = time();
     $timer->completed = $endreached;
     $DB->update_record('lesson_timer', $timer);
     // Update completion state.
     $cm = get_coursemodule_from_instance('lesson', $this->properties()->id, $this->properties()->course, false, MUST_EXIST);
     $course = get_course($cm->course);
     $completion = new completion_info($course);
     if ($completion->is_enabled($cm) && $this->properties()->completiontimespent > 0) {
         $completion->update_state($cm, COMPLETION_COMPLETE);
     }
     return $timer;
 }
/**
 * Updates Aggregates for a given user
 * and notify completion, if needed [feature #7]
 *
 * @param object $regiser
 * @param int $userId
 */
function attendanceregister__update_user_aggregates($register, $userId)
{
    global $DB;
    // Delete old aggregates
    $DB->delete_records('attendanceregister_aggregate', array('userid' => $userId, 'register' => $register->id));
    $aggregates = array();
    $queryParams = array('registerid' => $register->id, 'userid' => $userId);
    // Calculate aggregates of offline Sessions
    if ($register->offlinesessions) {
        // (note that refcourse has passed as first column to avoid warning of duplicate values in first column by get_records())
        $sql = 'SELECT sess.refcourse, sess.register, sess.userid, 0 AS onlinesess, SUM(sess.duration) AS duration, 0 AS total, 0 as grandtotal' . ' FROM {attendanceregister_session} sess' . ' WHERE sess.onlinesess = 0 AND sess.register = :registerid AND sess.userid = :userid' . ' GROUP BY sess.register, sess.userid, sess.refcourse';
        $offlinePerCourseAggregates = $DB->get_records_sql($sql, $queryParams);
        // Append records
        if ($offlinePerCourseAggregates) {
            $aggregates = array_merge($aggregates, $offlinePerCourseAggregates);
        }
        // Calculates total offline, regardless of RefCourse
        $sql = 'SELECT sess.register, sess.userid, 0 AS onlinesess, null AS refcourse, SUM(sess.duration) AS duration, 1 AS total, 0 as grandtotal' . ' FROM {attendanceregister_session} sess' . ' WHERE sess.onlinesess = 0 AND sess.register = :registerid AND sess.userid = :userid' . ' GROUP BY sess.register, sess.userid';
        $totalOfflineAggregate = $DB->get_record_sql($sql, $queryParams);
        // Append record
        if ($totalOfflineAggregate) {
            $aggregates[] = $totalOfflineAggregate;
        }
    }
    // Calculates aggregates of online Sessions (this is a total as no RefCourse may exist)
    $sql = 'SELECT sess.register, sess.userid, 1 AS onlinesess, null AS refcourse, SUM(sess.duration) AS duration, 1 AS total, 0 as grandtotal' . ' FROM {attendanceregister_session} sess' . ' WHERE sess.onlinesess = 1 AND sess.register = :registerid AND sess.userid = :userid' . ' GROUP BY sess.register, sess.userid';
    $onlineAggregate = $DB->get_record_sql($sql, $queryParams);
    // If User has no Session, generate an online Total record
    if (!$onlineAggregate) {
        $onlineAggregate = new stdClass();
        $onlineAggregate->register = $register->id;
        $onlineAggregate->userid = $userId;
        $onlineAggregate->onlinesess = 1;
        $onlineAggregate->refcourse = null;
        $onlineAggregate->duration = 0;
        $onlineAggregate->total = 1;
        $onlineAggregate->grandtotal = 0;
    }
    // Append record
    $aggregates[] = $onlineAggregate;
    // Calculates grand total
    $sql = 'SELECT sess.register, sess.userid, null AS onlinesess, null AS refcourse, SUM(sess.duration) AS duration, 0 AS total, 1 as grandtotal' . ' FROM {attendanceregister_session} sess' . ' WHERE sess.register = :registerid AND sess.userid = :userid' . ' GROUP BY sess.register, sess.userid';
    $grandTotalAggregate = $DB->get_record_sql($sql, $queryParams);
    // If User has no Session, generate a grandTotal record
    if (!$grandTotalAggregate) {
        $grandTotalAggregate = new stdClass();
        $grandTotalAggregate->register = $register->id;
        $grandTotalAggregate->userid = $userId;
        $grandTotalAggregate->onlinesess = null;
        $grandTotalAggregate->refcourse = null;
        $grandTotalAggregate->duration = 0;
        $grandTotalAggregate->total = 0;
        $grandTotalAggregate->grandtotal = 1;
    }
    // Add lastSessionLogout to GrandTotal
    $grandTotalAggregate->lastsessionlogout = attendanceregister__calculate_last_user_online_session_logout($register, $userId);
    // Append record
    $aggregates[] = $grandTotalAggregate;
    // Save all as Aggregates
    foreach ($aggregates as $aggregate) {
        $DB->insert_record('attendanceregister_aggregate', $aggregate);
    }
    // Notify completion if needed
    // (only if any completion condition is enabled)
    if (attendanceregister__isAnyCompletionConditionSpecified($register)) {
        // Retrieve Course-Module an Course instances
        $cm = get_coursemodule_from_instance('attendanceregister', $register->id, $register->course, null, MUST_EXIST);
        $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
        $completion = new completion_info($course);
        if ($completion->is_enabled($cm)) {
            // Check completion values
            $completionTrackedValues = array('totaldurationsecs' => $grandTotalAggregate->duration);
            $isComplete = attendanceregister__areCompletionConditionsMet($register, $completionTrackedValues);
            // Notify complete or incomplete
            if ($isComplete) {
                $completion->update_state($cm, COMPLETION_COMPLETE, $userId);
            } else {
                $completion->update_state($cm, COMPLETION_INCOMPLETE, $userId);
            }
        }
    }
}
Пример #16
0
/**
 * Sets activity completion state
 *
 * @param object $scorm object
 * @param int $userid User ID
 * @param int $completionstate Completion state
 * @param array $grades grades array of users with grades - used when $userid = 0
 */
function scorm_set_completion($scorm, $userid, $completionstate = COMPLETION_COMPLETE, $grades = array()) {
    $course = new stdClass();
    $course->id = $scorm->course;
    $completion = new completion_info($course);

    // Check if completion is enabled site-wide, or for the course.
    if (!$completion->is_enabled()) {
        return;
    }

    $cm = get_coursemodule_from_instance('scorm', $scorm->id, $scorm->course);
    if (empty($cm) || !$completion->is_enabled($cm)) {
            return;
    }

    if (empty($userid)) { // We need to get all the relevant users from $grades param.
        foreach ($grades as $grade) {
            $completion->update_state($cm, $completionstate, $grade->userid);
        }
    } else {
        $completion->update_state($cm, $completionstate, $userid);
    }
}
 /**
  * Updates completion status based on changes made to entire discussion.
  * @param bool $positive True if the changes will make things complete
  *   that were previously incomplete; false if they will make things
  *   incomplete that were previously complete
  */
 private function update_completion($positive)
 {
     // Get list of affected users (if any)
     $users = array();
     if ($this->forum->get_completion_replies() || $this->forum->get_completion_posts()) {
         // Affected users = everyone who posted
         $rootpost = $this->get_root_post();
         $posts = array();
         $rootpost->build_linear_children($posts);
         foreach ($posts as $post) {
             $users[$post->get_user()->id] = true;
         }
     } else {
         if ($this->forum->get_completion_discussions()) {
             // Affected users = discussion poster only
             $users[$this->get_poster()->id] = true;
         }
     }
     foreach ($users as $userid => $junk) {
         $course = $this->get_course();
         $cm = $this->get_course_module();
         $completion = new completion_info($course);
         $completion->update_state($cm, $positive ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE, $userid);
     }
 }
 /**
  * Log, update completion info and trigger event
  *
  * @param object $course
  * @param \context_module $context
  * @param object $cm
  * @param object $forum
  * @param object $discussion
  */
 public function trigger_discussion_created($course, \context_module $context, $cm, $forum, $discussion)
 {
     global $CFG;
     require_once $CFG->libdir . '/completionlib.php';
     $completion = new \completion_info($course);
     if ($completion->is_enabled($cm) && ($forum->completiondiscussions || $forum->completionposts)) {
         $completion->update_state($cm, COMPLETION_COMPLETE);
     }
     $params = array('context' => $context, 'objectid' => $discussion->id, 'other' => array('forumid' => $forum->id));
     $event = discussion_created::create($params);
     $event->add_record_snapshot('hsuforum_discussions', $discussion);
     $event->trigger();
 }
Пример #19
0
 /**
  * Revert to draft.
  *
  * @param int $userid
  * @return boolean
  */
 public function revert_to_draft($userid)
 {
     global $DB, $USER;
     // Need grade permission.
     require_capability('mod/assign:grade', $this->context);
     if ($this->get_instance()->teamsubmission) {
         $submission = $this->get_group_submission($userid, 0, false);
     } else {
         $submission = $this->get_user_submission($userid, false);
     }
     if (!$submission) {
         return false;
     }
     $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
     $this->update_submission($submission, $userid, true, $this->get_instance()->teamsubmission);
     // Give each submission plugin a chance to process the reverting to draft.
     $plugins = $this->get_submission_plugins();
     foreach ($plugins as $plugin) {
         if ($plugin->is_enabled() && $plugin->is_visible()) {
             $plugin->revert_to_draft($submission);
         }
     }
     // Update the modified time on the grade (grader modified).
     $grade = $this->get_user_grade($userid, true);
     $grade->grader = $USER->id;
     $this->update_grade($grade);
     $completion = new completion_info($this->get_course());
     if ($completion->is_enabled($this->get_course_module()) && $this->get_instance()->completionsubmit) {
         $completion->update_state($this->get_course_module(), COMPLETION_INCOMPLETE, $userid);
     }
     \mod_assign\event\submission_status_updated::create_from_submission($this, $submission)->trigger();
     return true;
 }
Пример #20
0
/**
 * @global object
 * @param array $attemptids
 * @param object $choice Choice main table row
 * @param object $cm Course-module object
 * @param object $course Course object
 * @return bool
 */
function choice_delete_responses($attemptids, $choice, $cm, $course)
{
    global $DB, $CFG;
    require_once $CFG->libdir . '/completionlib.php';
    if (!is_array($attemptids) || empty($attemptids)) {
        return false;
    }
    foreach ($attemptids as $num => $attemptid) {
        if (empty($attemptid)) {
            unset($attemptids[$num]);
        }
    }
    $completion = new completion_info($course);
    foreach ($attemptids as $attemptid) {
        if ($todelete = $DB->get_record('choice_answers', array('choiceid' => $choice->id, 'id' => $attemptid))) {
            $DB->delete_records('choice_answers', array('choiceid' => $choice->id, 'id' => $attemptid));
            // Update completion state
            if ($completion->is_enabled($cm) && $choice->completionsubmit) {
                $completion->update_state($cm, COMPLETION_INCOMPLETE, $attemptid);
            }
        }
    }
    return true;
}
Пример #21
0
/**
 * @global object
 * @param array $userids
 * @param object $choicegroup Choice main table row
 * @param object $cm Course-module object
 * @param object $course Course object
 * @return bool
 */
function choicegroup_delete_responses($userids, $choicegroup, $cm, $course)
{
    global $CFG, $DB, $context;
    require_once $CFG->libdir . '/completionlib.php';
    if (!is_array($userids) || empty($userids)) {
        return false;
    }
    foreach ($userids as $num => $userid) {
        if (empty($userid)) {
            unset($userids[$num]);
        }
    }
    $completion = new completion_info($course);
    $eventparams = array('context' => $context, 'objectid' => $choicegroup->id);
    foreach ($userids as $userid) {
        if ($current = choicegroup_get_user_answer($choicegroup, $userid)) {
            $currentgroup = $DB->get_record('groups', array('id' => $current->id), 'id,name', MUST_EXIST);
            if (groups_is_member($current->id, $userid)) {
                groups_remove_member($current->id, $userid);
                $event = \mod_choicegroup\event\choice_removed::create($eventparams);
                $event->add_record_snapshot('course_modules', $cm);
                $event->add_record_snapshot('course', $course);
                $event->add_record_snapshot('choicegroup', $choicegroup);
                $event->trigger();
            }
            // Update completion state
            if ($completion->is_enabled($cm) && $choicegroup->completionsubmit) {
                $completion->update_state($cm, COMPLETION_INCOMPLETE, $userid);
            }
        }
    }
    return true;
}
Пример #22
0
/**
 * Save the answer for the given survey
 *
 * @param  stdClass $survey   a survey object
 * @param  array $answersrawdata the answers to be saved
 * @param  stdClass $course   a course object (required for trigger the submitted event)
 * @param  stdClass $context  a context object (required for trigger the submitted event)
 * @since Moodle 3.0
 */
function survey_save_answers($survey, $answersrawdata, $course, $context)
{
    global $DB, $USER;
    $answers = array();
    // Sort through the data and arrange it.
    // This is necessary because some of the questions may have two answers, eg Question 1 -> 1 and P1.
    foreach ($answersrawdata as $key => $val) {
        if ($key != "userid" && $key != "id") {
            if (substr($key, 0, 1) == "q") {
                $key = clean_param(substr($key, 1), PARAM_ALPHANUM);
                // Keep everything but the 'q', number or P number.
            }
            if (substr($key, 0, 1) == "P") {
                $realkey = (int) substr($key, 1);
                $answers[$realkey][1] = $val;
            } else {
                $answers[$key][0] = $val;
            }
        }
    }
    // Now store the data.
    $timenow = time();
    $answerstoinsert = array();
    foreach ($answers as $key => $val) {
        if ($key != 'sesskey') {
            $newdata = new stdClass();
            $newdata->time = $timenow;
            $newdata->userid = $USER->id;
            $newdata->survey = $survey->id;
            $newdata->question = $key;
            if (!empty($val[0])) {
                $newdata->answer1 = $val[0];
            } else {
                $newdata->answer1 = "";
            }
            if (!empty($val[1])) {
                $newdata->answer2 = $val[1];
            } else {
                $newdata->answer2 = "";
            }
            $answerstoinsert[] = $newdata;
        }
    }
    if (!empty($answerstoinsert)) {
        $DB->insert_records("survey_answers", $answerstoinsert);
    }
    // Update completion state.
    $cm = get_coursemodule_from_instance('survey', $survey->id, $course->id);
    $completion = new completion_info($course);
    if (isloggedin() && !isguestuser() && $completion->is_enabled($cm) && $survey->completionsubmit) {
        $completion->update_state($cm, COMPLETION_COMPLETE);
    }
    $params = array('context' => $context, 'courseid' => $course->id, 'other' => array('surveyid' => $survey->id));
    $event = \mod_survey\event\response_submitted::create($params);
    $event->trigger();
}
Пример #23
0
 /**
  * Revert to draft.
  *
  * @param int $userid
  * @return boolean
  */
 public function revert_to_draft($userid)
 {
     global $DB, $USER;
     // Need grade permission.
     require_capability('mod/assign:grade', $this->context);
     if ($this->get_instance()->teamsubmission) {
         $submission = $this->get_group_submission($userid, 0, false);
     } else {
         $submission = $this->get_user_submission($userid, false);
     }
     if (!$submission) {
         return false;
     }
     $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
     $this->update_submission($submission, $userid, true, $this->get_instance()->teamsubmission);
     // Give each submission plugin a chance to process the reverting to draft.
     $plugins = $this->get_submission_plugins();
     foreach ($plugins as $plugin) {
         if ($plugin->is_enabled() && $plugin->is_visible()) {
             $plugin->revert_to_draft($submission);
         }
     }
     // Update the modified time on the grade (grader modified).
     $grade = $this->get_user_grade($userid, true);
     $grade->grader = $USER->id;
     $this->update_grade($grade);
     $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
     $completion = new completion_info($this->get_course());
     if ($completion->is_enabled($this->get_course_module()) && $this->get_instance()->completionsubmit) {
         $completion->update_state($this->get_course_module(), COMPLETION_INCOMPLETE, $userid);
     }
     $logmessage = get_string('reverttodraftforstudent', 'assign', array('id' => $user->id, 'fullname' => fullname($user)));
     $addtolog = $this->add_to_log('revert submission to draft', $logmessage, '', true);
     $params = array('context' => $this->context, 'objectid' => $submission->id, 'relateduserid' => $this->get_instance()->teamsubmission ? null : $userid, 'other' => array('newstatus' => $submission->status));
     $event = \mod_assign\event\submission_status_updated::create($params);
     $event->set_legacy_logdata($addtolog);
     $event->trigger();
     return true;
 }
Пример #24
0
 /**
  * Test update_activity_completion_status
  */
 public function test_get_activities_completion_status()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     $CFG->enablecompletion = true;
     $student = $this->getDataGenerator()->create_user();
     $teacher = $this->getDataGenerator()->create_user();
     $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1, 'groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1));
     $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id), array('completion' => 1));
     $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id), array('completion' => 1));
     $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
     $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id), array('completion' => 1, 'visible' => 0));
     $cmdata = get_coursemodule_from_id('data', $data->cmid);
     $cmforum = get_coursemodule_from_id('forum', $forum->cmid);
     $studentrole = $DB->get_record('role', array('shortname' => 'student'));
     $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
     $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
     $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
     $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
     // Teacher and student in different groups initially.
     groups_add_member($group1->id, $student->id);
     groups_add_member($group2->id, $teacher->id);
     $this->setUser($student);
     // Forum complete.
     $completion = new completion_info($course);
     $completion->update_state($cmforum, COMPLETION_COMPLETE);
     $result = core_completion_external::get_activities_completion_status($course->id, $student->id);
     // We need to execute the return values cleaning process to simulate the web service server.
     $result = external_api::clean_returnvalue(core_completion_external::get_activities_completion_status_returns(), $result);
     // We added 4 activities, but only 3 with completion enabled and one of those is hidden.
     $this->assertCount(2, $result['statuses']);
     $activitiesfound = 0;
     foreach ($result['statuses'] as $status) {
         if ($status['cmid'] == $forum->cmid and $status['modname'] == 'forum' and $status['instance'] == $forum->id) {
             $activitiesfound++;
             $this->assertEquals(COMPLETION_COMPLETE, $status['state']);
             $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']);
         } else {
             if ($status['cmid'] == $data->cmid and $status['modname'] == 'data' and $status['instance'] == $data->id) {
                 $activitiesfound++;
                 $this->assertEquals(COMPLETION_INCOMPLETE, $status['state']);
                 $this->assertEquals(COMPLETION_TRACKING_MANUAL, $status['tracking']);
             }
         }
     }
     $this->assertEquals(2, $activitiesfound);
     // Teacher should see students status, they are in different groups but the teacher can access all groups.
     $this->setUser($teacher);
     $result = core_completion_external::get_activities_completion_status($course->id, $student->id);
     // We need to execute the return values cleaning process to simulate the web service server.
     $result = external_api::clean_returnvalue(core_completion_external::get_activities_completion_status_returns(), $result);
     // We added 4 activities, but only 3 with completion enabled and one of those is hidden.
     $this->assertCount(3, $result['statuses']);
     // Change teacher role capabilities (disable access al goups).
     $context = context_course::instance($course->id);
     assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context);
     accesslib_clear_all_caches_for_unit_testing();
     try {
         $result = core_completion_external::get_activities_completion_status($course->id, $student->id);
         $this->fail('Exception expected due to groups permissions.');
     } catch (moodle_exception $e) {
         $this->assertEquals('accessdenied', $e->errorcode);
     }
     // Now add the teacher in the same group.
     groups_add_member($group1->id, $teacher->id);
     $result = core_completion_external::get_activities_completion_status($course->id, $student->id);
     // We need to execute the return values cleaning process to simulate the web service server.
     $result = external_api::clean_returnvalue(core_completion_external::get_activities_completion_status_returns(), $result);
     // We added 4 activities, but only 3 with completion enabled and one of those is hidden.
     $this->assertCount(3, $result['statuses']);
 }
Пример #25
0
/**
 * deletes a completed given by completedid.
 * all related data such values or tracking data also will be deleted
 *
 * @global object
 * @param int $completedid
 * @return boolean
 */
function feedback_delete_completed($completedid) {
    global $DB, $CFG;
    require_once($CFG->libdir.'/completionlib.php');

    if (!$completed = $DB->get_record('feedback_completed', array('id'=>$completedid))) {
        return false;
    }

    if (!$feedback = $DB->get_record('feedback', array('id'=>$completed->feedback))) {
        return false;
    }

    if (!$course = $DB->get_record('course', array('id'=>$feedback->course))) {
        return false;
    }

    if (!$cm = get_coursemodule_from_instance('feedback', $feedback->id)) {
        return false;
    }

    //first we delete all related values
    $DB->delete_records('feedback_value', array('completed'=>$completed->id));

    //now we delete all tracking data
    $params = array('completed'=>$completed->id, 'feedback'=>$completed->feedback);
    if ($tracking = $DB->get_record('feedback_tracking', $params)) {
        $DB->delete_records('feedback_tracking', array('completed'=>$completed->id));
    }

    // Update completion state
    $completion = new completion_info($course);
    if ($completion->is_enabled($cm) && $feedback->completionsubmit) {
        $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid);
    }
    //last we delete the completed-record
    return $DB->delete_records('feedback_completed', array('id'=>$completed->id));
}
Пример #26
0
        $DB->set_field('ouwiki_versions', 'deletedat', null, array('id' => $versionid));
        // Get first undeleted (current) page version (there must be one)
        $pageversions = ouwiki_get_page_history($pageversion->pageid, false, 0, 1);
        $currentpageversion = reset($pageversions);
        if (!$currentpageversion) {
            throw new Exception('Error deleting/undeleting ouwiki page version');
        }
        // Check if version that has been undeleted should be the new current version
        if ($pageversion->currentversionid != $currentpageversion->versionid) {
            // Set new current version id
            $DB->set_field('ouwiki_pages', 'currentversionid', $currentpageversion->versionid, array('id' => $pageversion->pageid));
        }
        // Update completion status for user
        $completion = new completion_info($course);
        if ($completion->is_enabled($cm) && ($ouwiki->completionedits || $ouwiki->completionpages)) {
            $completion->update_state($cm, COMPLETION_COMPLETE, $pageversion->userid);
        }
    }
} catch (Exception $e) {
    // Unlock page
    ouwiki_release_lock($pageversion->pageid);
    ouwiki_dberror('Error deleting/undeleting ouwiki page version ' . $e);
}
// Unlock page
ouwiki_release_lock($pageversion->pageid);
// Log delete or undelete action
$ouwikiparamsurl = ouwiki_display_wiki_parameters($pagename, $subwiki, $cm, OUWIKI_PARAMS_URL);
add_to_log($course->id, 'ouwiki', 'version' . $action, 'delete.php?' . $ouwikiparamsurl . '&amp;version=' . $versionid, '', $cm->id);
$redirecturl = new moodle_url('/mod/ouwiki/history.php');
// Redirect to view what is now the current version
redirect($redirecturl . '?' . $ouwikiparamsurl);
             default:
                 break;
         }
     }
     if ($optionIDPos > -1 && $userIDPos > -1 && $completedPos > -1) {
         array_shift($csvArr);
         $completion = new completion_info($course);
         foreach ($csvArr as $line) {
             if (count($line) >= 3) {
                 $user = $DB->get_record('booking_answers', array('bookingid' => $booking->id, 'userid' => $line[$userIDPos], 'optionid' => $line[$optionIDPos]));
                 if ($user !== FALSE) {
                     $user->completed = $line[$completedPos];
                     $user->timemodified = time();
                     $DB->update_record('booking_answers', $user, false);
                     if ($completion->is_enabled($cm) && $booking->enablecompletion && $user->completed == 0) {
                         $completion->update_state($cm, COMPLETION_INCOMPLETE, $user->userid);
                     }
                     if ($completion->is_enabled($cm) && $booking->enablecompletion && $user->completed == 1) {
                         $completion->update_state($cm, COMPLETION_COMPLETE, $user->userid);
                     }
                 }
             }
         }
         redirect($urlRedirect, get_string('importfinished', 'booking'), 5);
     } else {
         redirect($urlRedirect, get_string('wrongfile', 'booking'), 5);
     }
     //In this case you process validated data. $mform->get_data() returns data posted in form.
 } else {
     echo $OUTPUT->header();
     echo $OUTPUT->heading(get_string("importexceltitle", "booking"), 3, 'helptitle', 'uniqueid');
Пример #28
0
    /**
     * revert to draft
     * Uses url parameter userid
     *
     * @param int $userid
     * @return void
     */
    private function process_revert_to_draft($userid = 0) {
        global $DB, $USER;

        // Need grade permission
        require_capability('mod/assign:grade', $this->context);
        require_sesskey();

        if (!$userid) {
            $userid = required_param('userid', PARAM_INT);
        }

        $submission = $this->get_user_submission($userid, false);

        if (!$submission) {
            return;
        }
        $submission->status = ASSIGN_SUBMISSION_STATUS_DRAFT;
        $this->update_submission($submission, $USER->id, true, $this->get_instance()->teamsubmission);

        // Update the modified time on the grade (grader modified).
        $grade = $this->get_user_grade($userid, true);
        $grade->grader = $USER->id;
        $this->update_grade($grade);

        $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);

        $completion = new completion_info($this->get_course());
        if ($completion->is_enabled($this->get_course_module()) && $this->get_instance()->completionsubmit) {
            $completion->update_state($this->get_course_module(), COMPLETION_INCOMPLETE, $userid);
        }
        $this->add_to_log('revert submission to draft', get_string('reverttodraftforstudent', 'assign', array('id'=>$user->id, 'fullname'=>fullname($user))));

    }
Пример #29
0
/**
 * Deletes a single forum post.
 *
 * @global object
 * @param object $post Forum post object
 * @param mixed $children Whether to delete children. If false, returns false
 *   if there are any children (without deleting the post). If true,
 *   recursively deletes all children. If set to special value 'ignore', deletes
 *   post regardless of children (this is for use only when deleting all posts
 *   in a disussion).
 * @param object $course Course
 * @param object $cm Course-module
 * @param object $forum Forum
 * @param bool $skipcompletion True to skip updating completion state if it
 *   would otherwise be updated, i.e. when deleting entire forum anyway.
 * @return bool
 */
function forum_delete_post($post, $children, $course, $cm, $forum, $skipcompletion=false) {
    global $DB, $CFG;
    require_once($CFG->libdir.'/completionlib.php');

    $context = context_module::instance($cm->id);

    if ($children !== 'ignore' && ($childposts = $DB->get_records('forum_posts', array('parent'=>$post->id)))) {
       if ($children) {
           foreach ($childposts as $childpost) {
               forum_delete_post($childpost, true, $course, $cm, $forum, $skipcompletion);
           }
       } else {
           return false;
       }
    }

    //delete ratings
    require_once($CFG->dirroot.'/rating/lib.php');
    $delopt = new stdClass;
    $delopt->contextid = $context->id;
    $delopt->component = 'mod_forum';
    $delopt->ratingarea = 'post';
    $delopt->itemid = $post->id;
    $rm = new rating_manager();
    $rm->delete_ratings($delopt);

    //delete attachments
    $fs = get_file_storage();
    $fs->delete_area_files($context->id, 'mod_forum', 'attachment', $post->id);
    $fs->delete_area_files($context->id, 'mod_forum', 'post', $post->id);

    if ($DB->delete_records("forum_posts", array("id" => $post->id))) {

        forum_tp_delete_read_records(-1, $post->id);

    // Just in case we are deleting the last post
        forum_discussion_update_last_post($post->discussion);

        // Update completion state if we are tracking completion based on number of posts
        // But don't bother when deleting whole thing

        if (!$skipcompletion) {
            $completion = new completion_info($course);
            if ($completion->is_enabled($cm) == COMPLETION_TRACKING_AUTOMATIC &&
               ($forum->completiondiscussions || $forum->completionreplies || $forum->completionposts)) {
                $completion->update_state($cm, COMPLETION_INCOMPLETE, $post->userid);
            }
        }

        return true;
    }
    return false;
}
 public function view()
 {
     global $CFG, $USER, $PAGE, $OUTPUT;
     $PAGE->set_title(format_string($this->name));
     $PAGE->set_heading(format_string($this->course->fullname));
     // Initialise the JavaScript.
     $PAGE->requires->js_init_call('M.mod_questionnaire.init_attempt_form', null, false, questionnaire_get_js_module());
     echo $OUTPUT->header();
     $questionnaire = $this;
     if (!$this->cm->visible && !$this->capabilities->viewhiddenactivities) {
         notice(get_string("activityiscurrentlyhidden"));
     }
     if (!$this->capabilities->view) {
         echo '<br/>';
         questionnaire_notify(get_string("noteligible", "questionnaire", $this->name));
         echo '<div><a href="' . $CFG->wwwroot . '/course/view.php?id=' . $this->course->id . '">' . get_string("continue") . '</a></div>';
         exit;
     }
     // Print the main part of the page.
     if (!$this->is_active()) {
         echo '<div class="notifyproblem">' . get_string('notavail', 'questionnaire') . '</div>';
     } else {
         if (!$this->is_open()) {
             echo '<div class="notifyproblem">' . get_string('notopen', 'questionnaire', userdate($this->opendate)) . '</div>';
         } else {
             if ($this->is_closed()) {
                 echo '<div class="notifyproblem">' . get_string('closed', 'questionnaire', userdate($this->closedate)) . '</div>';
             } else {
                 if (!$this->user_is_eligible($USER->id)) {
                     echo '<div class="notifyproblem">' . get_string('noteligible', 'questionnaire') . '</div>';
                 } else {
                     if ($this->user_can_take($USER->id)) {
                         $quser = $USER->id;
                         if ($this->survey->realm == 'template') {
                             print_string('templatenotviewable', 'questionnaire');
                             echo $OUTPUT->footer($this->course);
                             exit;
                         }
                         $msg = $this->print_survey($USER->id, $quser);
                         // If Questionnaire was submitted with all required fields completed ($msg is empty),
                         // then record the submittal.
                         $viewform = data_submitted($CFG->wwwroot . "/mod/questionnaire/complete.php");
                         if (!empty($viewform->rid)) {
                             $viewform->rid = (int) $viewform->rid;
                         }
                         if (!empty($viewform->sec)) {
                             $viewform->sec = (int) $viewform->sec;
                         }
                         if (data_submitted() && confirm_sesskey() && isset($viewform->submit) && isset($viewform->submittype) && $viewform->submittype == "Submit Survey" && empty($msg)) {
                             $this->response_delete($viewform->rid, $viewform->sec);
                             $this->rid = $this->response_insert($this->survey->id, $viewform->sec, $viewform->rid, $quser);
                             $this->response_commit($this->rid);
                             // If it was a previous save, rid is in the form...
                             if (!empty($viewform->rid) && is_numeric($viewform->rid)) {
                                 $rid = $viewform->rid;
                                 // Otherwise its in this object.
                             } else {
                                 $rid = $this->rid;
                             }
                             questionnaire_record_submission($this, $USER->id, $rid);
                             if ($this->grade != 0) {
                                 $questionnaire = new stdClass();
                                 $questionnaire->id = $this->id;
                                 $questionnaire->name = $this->name;
                                 $questionnaire->grade = $this->grade;
                                 $questionnaire->cmidnumber = $this->cm->idnumber;
                                 $questionnaire->courseid = $this->course->id;
                                 questionnaire_update_grades($questionnaire, $quser);
                             }
                             // Update completion state.
                             $completion = new completion_info($this->course);
                             if ($completion->is_enabled($this->cm) && $this->completionsubmit) {
                                 $completion->update_state($this->cm, COMPLETION_COMPLETE);
                             }
                             // Log this submitted response.
                             $context = context_module::instance($this->cm->id);
                             $anonymous = $this->respondenttype == 'anonymous';
                             $params = array('context' => $context, 'courseid' => $this->course->id, 'relateduserid' => $USER->id, 'anonymous' => $anonymous, 'other' => array('questionnaireid' => $questionnaire->id));
                             $event = \mod_questionnaire\event\attempt_submitted::create($params);
                             $event->trigger();
                             $this->response_send_email($this->rid);
                             $this->response_goto_thankyou();
                         }
                     } else {
                         switch ($this->qtype) {
                             case QUESTIONNAIREDAILY:
                                 $msgstring = ' ' . get_string('today', 'questionnaire');
                                 break;
                             case QUESTIONNAIREWEEKLY:
                                 $msgstring = ' ' . get_string('thisweek', 'questionnaire');
                                 break;
                             case QUESTIONNAIREMONTHLY:
                                 $msgstring = ' ' . get_string('thismonth', 'questionnaire');
                                 break;
                             default:
                                 $msgstring = '';
                                 break;
                         }
                         echo '<div class="notifyproblem">' . get_string("alreadyfilled", "questionnaire", $msgstring) . '</div>';
                     }
                 }
             }
         }
     }
     // Finish the page.
     echo $OUTPUT->footer($this->course);
 }