public function check_answer() { global $DB, $CFG; $formattextdefoptions = new stdClass(); $formattextdefoptions->noclean = true; $formattextdefoptions->para = false; $answers = $this->get_answers(); shuffle($answers); $params = array('answers' => $answers, 'lessonid' => $this->lesson->id, 'contents' => $this->get_contents()); $mform = new lesson_display_answer_form_truefalse($CFG->wwwroot . '/mod/lesson/continue.php', $params); $data = $mform->get_data(); require_sesskey(); $result = parent::check_answer(); if (empty($data->answerid)) { $result->noanswer = true; return $result; } $result->answerid = $data->answerid; $answer = $DB->get_record("lesson_answers", array("id" => $result->answerid), '*', MUST_EXIST); if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { $result->correctanswer = true; } if ($this->lesson->custom) { if ($answer->score > 0) { $result->correctanswer = true; } else { $result->correctanswer = false; } } $result->newpageid = $answer->jumpto; $result->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); $result->studentanswer = $result->userresponse = $answer->answer; return $result; }
public function check_answer() { global $CFG; $result = parent::check_answer(); $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents())); $data = $mform->get_data(); require_sesskey(); $formattextdefoptions = new stdClass(); $formattextdefoptions->noclean = true; $formattextdefoptions->para = false; // set defaults $result->response = ''; $result->newpageid = 0; if (!isset($data->answer) || !is_numeric($data->answer)) { $result->noanswer = true; return $result; } else { // Just doing default PARAM_RAW, not doing PARAM_INT because it could be a float. $result->useranswer = (float)$data->answer; } $result->studentanswer = $result->userresponse = $result->useranswer; $answers = $this->get_answers(); foreach ($answers as $answer) { $answer = parent::rewrite_answers_urls($answer); if (strpos($answer->answer, ':')) { // there's a pairs of values list($min, $max) = explode(':', $answer->answer); $minimum = (float) $min; $maximum = (float) $max; } else { // there's only one value $minimum = (float) $answer->answer; $maximum = $minimum; } if (($result->useranswer >= $minimum) && ($result->useranswer <= $maximum)) { $result->newpageid = $answer->jumpto; $result->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); if ($this->lesson->jumpto_is_correct($this->properties->id, $result->newpageid)) { $result->correctanswer = true; } if ($this->lesson->custom) { if ($answer->score > 0) { $result->correctanswer = true; } else { $result->correctanswer = false; } } $result->answerid = $answer->id; return $result; } } return $result; }
/** * Add a new section with the provided title and (optional) summary * * @return string */ public function addsection_action() { global $CFG, $PAGE, $DB; require_once $CFG->dirroot . '/course/lib.php'; $sectioname = required_param('newsection', PARAM_TEXT); $summary = optional_param('summary', '', PARAM_RAW); require_sesskey(); $courseid = $PAGE->context->get_course_context()->instanceid; $course = course_get_format($courseid)->get_course(); $course->numsections++; course_get_format($course)->update_course_format_options(array('numsections' => $course->numsections)); course_create_sections_if_missing($course, range(0, $course->numsections)); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info($course->numsections, MUST_EXIST); $DB->set_field('course_sections', 'name', $sectioname, array('id' => $section->id)); $DB->set_field('course_sections', 'summary', $summary, array('id' => $section->id)); $DB->set_field('course_sections', 'summaryformat', FORMAT_HTML, array('id' => $section->id)); rebuild_course_cache($course->id); redirect(course_get_url($course, $section->section)); }
/** * Toggle Post Flags */ public function flag_action() { global $DB; require_sesskey(); $postid = required_param('postid', PARAM_INT); $flag = required_param('flag', PARAM_ALPHA); $returnurl = required_param('returnurl', PARAM_LOCALURL); $flags = $DB->get_field('hsuforum_posts', 'flags', array('id' => $postid), MUST_EXIST); $flaglib = new \hsuforum_lib_flag(); $newflags = $flaglib->toggle_flag($flags, $flag); if ($newflags != $flags) { $updateok = $DB->set_field('hsuforum_posts', 'flags', $newflags, array('id' => $postid)); if (AJAX_SCRIPT && !$updateok) { http_response_code(500); } } if (!AJAX_SCRIPT) { redirect(new \moodle_url($returnurl)); } }
/** * Check for a sess key and then call add_attempt. * * @param int $userid int The user to add the attempt for * @return bool - true if successful. */ protected function process_add_attempt($userid) { require_sesskey(); return $this->add_attempt($userid); }
/** * main invoke method, it sets the postaction attribute * if possible and checks sesskey_protected if needed */ function invoke() { global $SESSION; // Sesskey protection if ($this->sesskey_protected) { require_sesskey(); } // If we are used any dir, save it in the lastused session object // Some actions can use it to perform positioning if ($lastused = optional_param('dir', NULL, PARAM_PATH)) { $SESSION->lastused = $lastused; } $this->postaction = optional_param('postaction', NULL, PARAM_ALPHAEXT); // Avoid being recursive if ($this->title == $this->postaction) { $this->postaction = NULL; } }
/** * Handle showing/processing the submission from the block editing form. * @return boolean true if the form was submitted and the new config saved. Does not * return if the editing form was displayed. False otherwise. */ public function process_url_move() { global $CFG, $DB, $PAGE; $blockid = optional_param('bui_moveid', null, PARAM_INT); if (!$blockid) { return false; } require_sesskey(); $block = $this->find_instance($blockid); if (!$this->page->user_can_edit_blocks()) { throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock')); } $newregion = optional_param('bui_newregion', '', PARAM_ALPHANUMEXT); $newweight = optional_param('bui_newweight', null, PARAM_FLOAT); if (!$newregion || is_null($newweight)) { // Don't have a valid target position yet, must be just starting the move. $this->movingblock = $blockid; $this->page->ensure_param_not_in_url('bui_moveid'); return false; } if (!$this->is_known_region($newregion)) { throw new moodle_exception('unknownblockregion', '', $this->page->url, $newregion); } // Move this block. This may involve moving other nearby blocks. $blocks = $this->birecordsbyregion[$newregion]; $maxweight = self::MAX_WEIGHT; $minweight = -self::MAX_WEIGHT; // Initialise the used weights and spareweights array with the default values $spareweights = array(); $usedweights = array(); for ($i = $minweight; $i <= $maxweight; $i++) { $spareweights[$i] = $i; $usedweights[$i] = array(); } // Check each block and sort out where we have used weights foreach ($blocks as $bi) { if ($bi->weight > $maxweight) { // If this statement is true then the blocks weight is more than the // current maximum. To ensure that we can get the best block position // we will initialise elements within the usedweights and spareweights // arrays between the blocks weight (which will then be the new max) and // the current max $parseweight = $bi->weight; while (!array_key_exists($parseweight, $usedweights)) { $usedweights[$parseweight] = array(); $spareweights[$parseweight] = $parseweight; $parseweight--; } $maxweight = $bi->weight; } else { if ($bi->weight < $minweight) { // As above except this time the blocks weight is LESS than the // the current minimum, so we will initialise the array from the // blocks weight (new minimum) to the current minimum $parseweight = $bi->weight; while (!array_key_exists($parseweight, $usedweights)) { $usedweights[$parseweight] = array(); $spareweights[$parseweight] = $parseweight; $parseweight++; } $minweight = $bi->weight; } } if ($bi->id != $block->instance->id) { unset($spareweights[$bi->weight]); $usedweights[$bi->weight][] = $bi->id; } } // First we find the nearest gap in the list of weights. $bestdistance = max(abs($newweight - self::MAX_WEIGHT), abs($newweight + self::MAX_WEIGHT)) + 1; $bestgap = null; foreach ($spareweights as $spareweight) { if (abs($newweight - $spareweight) < $bestdistance) { $bestdistance = abs($newweight - $spareweight); $bestgap = $spareweight; } } // If there is no gap, we have to go outside -self::MAX_WEIGHT .. self::MAX_WEIGHT. if (is_null($bestgap)) { $bestgap = self::MAX_WEIGHT + 1; while (!empty($usedweights[$bestgap])) { $bestgap++; } } // Now we know the gap we are aiming for, so move all the blocks along. if ($bestgap < $newweight) { $newweight = floor($newweight); for ($weight = $bestgap + 1; $weight <= $newweight; $weight++) { foreach ($usedweights[$weight] as $biid) { $this->reposition_block($biid, $newregion, $weight - 1); } } $this->reposition_block($block->instance->id, $newregion, $newweight); } else { $newweight = ceil($newweight); for ($weight = $bestgap - 1; $weight >= $newweight; $weight--) { if (array_key_exists($weight, $usedweights)) { foreach ($usedweights[$weight] as $biid) { $this->reposition_block($biid, $newregion, $weight + 1); } } } $this->reposition_block($block->instance->id, $newregion, $newweight); } $this->page->ensure_param_not_in_url('bui_moveid'); $this->page->ensure_param_not_in_url('bui_newregion'); $this->page->ensure_param_not_in_url('bui_newweight'); return true; }
/** * Returns draft area itemid for a given element. * * @category files * @param string $elname name of formlib editor element, or a hidden form field that stores the draft area item id, etc. * @return int the itemid, or 0 if there is not one yet. */ function file_get_submitted_draft_itemid($elname) { // this is a nasty hack, ideally all new elements should use arrays here or there should be a new parameter if (!isset($_REQUEST[$elname])) { return 0; } if (is_array($_REQUEST[$elname])) { $param = optional_param_array($elname, 0, PARAM_INT); if (!empty($param['itemid'])) { $param = $param['itemid']; } else { debugging('Missing itemid, maybe caused by unset maxfiles option', DEBUG_DEVELOPER); return false; } } else { $param = optional_param($elname, 0, PARAM_INT); } if ($param) { require_sesskey(); } return $param; }
/** * Returns draft area itemid for a given element. * * @param string $elname name of formlib editor element, or a hidden form field that stores the draft area item id, etc. * @return integer the itemid, or 0 if there is not one yet. */ function file_get_submitted_draft_itemid($elname) { $param = optional_param($elname, 0, PARAM_INT); if ($param) { require_sesskey(); } if (is_array($param)) { if (!empty($param['itemid'])) { $param = $param['itemid']; } else { debugging('Missing itemid, maybe caused by unset maxfiles option', DEBUG_DEVELOPER); return false; } } return $param; }
public function construction_override($pageid, lesson $lesson) { global $CFG, $PAGE, $DB; require_sesskey(); $timenow = time(); // the new page is not the first page (end of cluster always comes after an existing page) if (!($page = $DB->get_record("lesson_pages", array("id" => $pageid)))) { print_error('cannotfindpages', 'lesson'); } // could put code in here to check if the user really can insert an end of cluster $newpage = new stdClass(); $newpage->lessonid = $lesson->id; $newpage->prevpageid = $pageid; $newpage->nextpageid = $page->nextpageid; $newpage->qtype = $this->qtype; $newpage->timecreated = $timenow; $newpage->title = get_string("endofclustertitle", "lesson"); $newpage->contents = get_string("endofclustertitle", "lesson"); $newpageid = $DB->insert_record("lesson_pages", $newpage); // update the linked list... $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); if ($page->nextpageid) { // the new page is not the last page $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); } // ..and the single "answer" $newanswer = new stdClass(); $newanswer->lessonid = $lesson->id; $newanswer->pageid = $newpageid; $newanswer->timecreated = $timenow; $newanswer->jumpto = LESSON_NEXTPAGE; $newanswerid = $DB->insert_record("lesson_answers", $newanswer); $lesson->add_message(get_string('addedendofcluster', 'lesson'), 'notifysuccess'); redirect($CFG->wwwroot . '/mod/lesson/edit.php?id=' . $PAGE->cm->id); }
public function check_answer() { global $USER, $DB, $PAGE, $CFG; require_sesskey(); $newpageid = optional_param('jumpto', NULL, PARAM_INT); // going to insert into lesson_branch if ($newpageid == LESSON_RANDOMBRANCH) { $branchflag = 1; } else { $branchflag = 0; } if ($grades = $DB->get_records("lesson_grades", array("lessonid" => $this->lesson->id, "userid" => $USER->id), "grade DESC")) { $retries = count($grades); } else { $retries = 0; } $branch = new stdClass; $branch->lessonid = $this->lesson->id; $branch->userid = $USER->id; $branch->pageid = $this->properties->id; $branch->retry = $retries; $branch->flag = $branchflag; $branch->timeseen = time(); $DB->insert_record("lesson_branch", $branch); // this is called when jumping to random from a branch table $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); if($newpageid == LESSON_UNSEENBRANCHPAGE) { if (has_capability('mod/lesson:manage', $context)) { $newpageid = LESSON_NEXTPAGE; } else { $newpageid = lesson_unseen_question_jump($this->lesson, $USER->id, $this->properties->id); // this may return 0 } } // convert jumpto page into a proper page id if ($newpageid == 0) { $newpageid = $this->properties->id; } elseif ($newpageid == LESSON_NEXTPAGE) { if (!$newpageid = $this->nextpageid) { // no nextpage go to end of lesson $newpageid = LESSON_EOL; } } elseif ($newpageid == LESSON_PREVIOUSPAGE) { $newpageid = $this->prevpageid; } elseif ($newpageid == LESSON_RANDOMPAGE) { $newpageid = lesson_random_question_jump($this->lesson, $this->properties->id); } elseif ($newpageid == LESSON_RANDOMBRANCH) { $newpageid = lesson_unseen_branch_jump($this->lesson, $USER->id); } // no need to record anything in lesson_attempts redirect(new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id,'pageid'=>$newpageid))); }
/** * save grade * * @param moodleform $mform * @return bool - was the grade saved */ private function process_save_grade(&$mform) { global $USER, $DB, $CFG; // Include grade form require_once $CFG->dirroot . '/mod/assign/gradeform.php'; // Need submit permission to submit an assignment require_capability('mod/assign:grade', $this->context); require_sesskey(); $rownum = required_param('rownum', PARAM_INT); $useridlist = optional_param('useridlist', '', PARAM_TEXT); if ($useridlist) { $useridlist = explode(',', $useridlist); } else { $useridlist = $this->get_grading_userid_list(); } $last = false; $userid = $useridlist[$rownum]; if ($rownum == count($useridlist) - 1) { $last = true; } $data = new stdClass(); $mform = new mod_assign_grade_form(null, array($this, $data, array('rownum' => $rownum, 'useridlist' => $useridlist, 'last' => false)), 'post', '', array('class' => 'gradeform')); if ($formdata = $mform->get_data()) { $grade = $this->get_user_grade($userid, true); $gradingdisabled = $this->grading_disabled($userid); $gradinginstance = $this->get_grading_instance($userid, $gradingdisabled); if (!$gradingdisabled) { if ($gradinginstance) { $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id); } else { // handle the case when grade is set to No Grade if (isset($formdata->grade)) { $grade->grade = grade_floatval(unformat_float($formdata->grade)); } } } $grade->grader = $USER->id; $adminconfig = $this->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; // call save in plugins foreach ($this->feedbackplugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { if (!$plugin->save($grade, $formdata)) { $result = false; print_error($plugin->get_error()); } if ('assignfeedback_' . $plugin->get_type() == $gradebookplugin) { // this is the feedback plugin chose to push comments to the gradebook $grade->feedbacktext = $plugin->text_for_gradebook($grade); $grade->feedbackformat = $plugin->format_for_gradebook($grade); } } } $this->process_outcomes($userid, $formdata); $grade->mailed = 0; $this->update_grade($grade); $this->notify_grade_modified($grade); $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); $this->add_to_log('grade submission', $this->format_grade_for_log($grade)); } else { return false; } return true; }
/** * Render coupon page (including header / footer). * * @param int $id block instance id * @param int $filter table filter * @param int $ownerid the owner id of the coupons. Set 0 or NULL to see all. * @return string */ protected function page_coupons($id, $filter, $ownerid = null) { // Actions anyone? $action = optional_param('action', null, PARAM_ALPHA); if ($action === 'delete' && $filter === \block_coupon\tables\coupons::UNUSED) { global $DB; require_sesskey(); $id = required_param('itemid', PARAM_INT); $DB->delete_records('block_coupon', array('id' => $id)); $DB->delete_records('block_coupon_cohorts', array('couponid' => $id)); $DB->delete_records('block_coupon_groups', array('couponid' => $id)); $DB->delete_records('block_coupon_courses', array('couponid' => $id)); redirect($this->page->url, get_string('coupon:deleted', 'block_coupon')); } // Table instance. $table = new \block_coupon\tables\coupons($ownerid, $filter); $table->baseurl = $this->page->url; $table->is_downloadable(true); $table->show_download_buttons_at(array(TABLE_P_BOTTOM, TABLE_P_TOP)); $download = optional_param('download', '', PARAM_ALPHA); if (!empty($download)) { $table->is_downloading($download, 'coupons', 'coupons'); $table->render(25); exit; } $selectedtab = ''; switch ($filter) { case \block_coupon\tables\coupons::UNUSED: $selectedtab = 'cpunused'; break; case \block_coupon\tables\coupons::USED: $selectedtab = 'cpused'; break; } $out = ''; $out .= $this->header(); $out .= html_writer::start_div('block-coupon-container'); $out .= html_writer::start_div(); $out .= $this->get_tabs($this->page->context, $selectedtab, array('id' => $id)); $out .= html_writer::end_div(); ob_start(); $table->render(25); $out .= ob_get_clean(); $out .= html_writer::end_div(); $out .= $this->footer(); return $out; }
/** * Call an external function validating all params/returns correctly. * * Note that an external function may modify the state of the current page, so this wrapper * saves and restores tha PAGE and COURSE global variables before/after calling the external function. * * @param string $function A webservice function name. * @param array $args Params array (named params) * @param boolean $ajaxonly If true, an extra check will be peformed to see if ajax is required. * @return array containing keys for error (bool), exception and data. */ public static function call_external_function($function, $args, $ajaxonly = false) { global $PAGE, $COURSE, $CFG, $SITE; require_once $CFG->libdir . "/pagelib.php"; $externalfunctioninfo = self::external_function_info($function); $currentpage = $PAGE; $currentcourse = $COURSE; $response = array(); try { // Taken straight from from setup.php. if (!empty($CFG->moodlepageclass)) { if (!empty($CFG->moodlepageclassfile)) { require_once $CFG->moodlepageclassfile; } $classname = $CFG->moodlepageclass; } else { $classname = 'moodle_page'; } $PAGE = new $classname(); $COURSE = clone $SITE; if ($ajaxonly && !$externalfunctioninfo->allowed_from_ajax) { throw new moodle_exception('servicenotavailable', 'webservice'); } // Do not allow access to write or delete webservices as a public user. if ($externalfunctioninfo->loginrequired) { if (defined('NO_MOODLE_COOKIES') && NO_MOODLE_COOKIES && !PHPUNIT_TEST) { throw new moodle_exception('servicenotavailable', 'webservice'); } if (!isloggedin()) { throw new moodle_exception('servicenotavailable', 'webservice'); } else { require_sesskey(); } } // Validate params, this also sorts the params properly, we need the correct order in the next part. $callable = array($externalfunctioninfo->classname, 'validate_parameters'); $params = call_user_func($callable, $externalfunctioninfo->parameters_desc, $args); // Execute - gulp! $callable = array($externalfunctioninfo->classname, $externalfunctioninfo->methodname); $result = call_user_func_array($callable, array_values($params)); // Validate the return parameters. if ($externalfunctioninfo->returns_desc !== null) { $callable = array($externalfunctioninfo->classname, 'clean_returnvalue'); $result = call_user_func($callable, $externalfunctioninfo->returns_desc, $result); } $response['error'] = false; $response['data'] = $result; } catch (Exception $e) { $exception = get_exception_info($e); unset($exception->a); if (!debugging('', DEBUG_DEVELOPER)) { unset($exception->debuginfo); unset($exception->backtrace); } $response['error'] = true; $response['exception'] = $exception; // Do not process the remaining requests. } $PAGE = $currentpage; $COURSE = $currentcourse; return $response; }
public function check_answer() { global $CFG, $PAGE; $formattextdefoptions = new stdClass(); $formattextdefoptions->noclean = true; $formattextdefoptions->para = false; $result = parent::check_answer(); $mform = $this->make_answer_form(); $data = $mform->get_data(); require_sesskey(); if (!$data) { redirect(new moodle_url('/mod/lesson/view.php', array('id' => $PAGE->cm->id, 'pageid' => $this->properties->id))); } $response = $data->response; if (!is_array($response)) { $result->noanswer = true; return $result; } $answers = $this->get_answers(); $correct = array_shift($answers); $wrong = array_shift($answers); foreach ($answers as $key => $answer) { if ($answer->answer === '' or $answer->response === '') { // incomplete option! unset($answers[$key]); } } // get he users exact responses for record keeping $hits = 0; $userresponse = array(); foreach ($response as $key => $value) { foreach ($answers as $answer) { if ($value === $answer->response) { $userresponse[] = $answer->id; } if ((int) $answer->id === (int) $key) { $result->studentanswer .= '<br />' . format_text($answer->answer, $answer->answerformat, $formattextdefoptions) . ' = ' . $value; } if ((int) $answer->id === (int) $key and $value === $answer->response) { $hits++; } } } $result->userresponse = implode(",", $userresponse); if ($hits == count($answers)) { $result->correctanswer = true; $result->response = format_text($correct->answer, $correct->answerformat, $formattextdefoptions); $result->answerid = $correct->id; $result->newpageid = $correct->jumpto; } else { $result->correctanswer = false; $result->response = format_text($wrong->answer, $wrong->answerformat, $formattextdefoptions); $result->answerid = $wrong->id; $result->newpageid = $wrong->jumpto; } return $result; }
/** * Hook method to handle the remote request to install an add-on * * This is used as a callback when the admin picks a plugin version in the * Moodle Plugins directory and is redirected back to their site to install * it. * * This hook is called early from admin/tool/installaddon/index.php page so that * it has opportunity to take over the UI. * * @param tool_installaddon_renderer $output * @param string|null $request * @param bool $confirmed */ public function handle_remote_request(tool_installaddon_renderer $output, $request, $confirmed = false) { global $CFG; require_once dirname(__FILE__) . '/pluginfo_client.php'; if (is_null($request)) { return; } $data = $this->decode_remote_request($request); if ($data === false) { echo $output->remote_request_invalid_page($this->index_url()); exit; } list($plugintype, $pluginname) = normalize_component($data->component); $plugintypepath = $this->get_plugintype_root($plugintype); if (file_exists($plugintypepath . '/' . $pluginname)) { echo $output->remote_request_alreadyinstalled_page($data, $this->index_url()); exit; } if (!$this->is_plugintype_writable($plugintype)) { $continueurl = $this->index_url(array('installaddonrequest' => $request)); echo $output->remote_request_permcheck_page($data, $plugintypepath, $continueurl, $this->index_url()); exit; } $continueurl = $this->index_url(array('installaddonrequest' => $request, 'confirm' => 1, 'sesskey' => sesskey())); if (!$confirmed) { echo $output->remote_request_confirm_page($data, $continueurl, $this->index_url()); exit; } // The admin has confirmed their intention to install the add-on. require_sesskey(); // Fetch the plugin info. The essential information is the URL to download the ZIP // and the MD5 hash of the ZIP, obtained via HTTPS. $client = tool_installaddon_pluginfo_client::instance(); try { $pluginfo = $client->get_pluginfo($data->component, $data->version); } catch (tool_installaddon_pluginfo_exception $e) { if (debugging()) { throw $e; } else { echo $output->remote_request_pluginfo_exception($data, $e, $this->index_url()); exit; } } // Fetch the ZIP with the plugin version $jobid = md5(rand() . uniqid('', true)); $sourcedir = make_temp_directory('tool_installaddon/' . $jobid . '/source'); $zipfilename = 'downloaded.zip'; try { $this->download_file($pluginfo->downloadurl, $sourcedir . '/' . $zipfilename); } catch (tool_installaddon_installer_exception $e) { if (debugging()) { throw $e; } else { echo $output->installer_exception($e, $this->index_url()); exit; } } // Check the MD5 checksum $md5expected = $pluginfo->downloadmd5; $md5actual = md5_file($sourcedir . '/' . $zipfilename); if ($md5expected !== $md5actual) { $e = new tool_installaddon_installer_exception('err_zip_md5', array('expected' => $md5expected, 'actual' => $md5actual)); if (debugging()) { throw $e; } else { echo $output->installer_exception($e, $this->index_url()); exit; } } // Redirect to the validation page. $nexturl = new moodle_url('/admin/tool/installaddon/validate.php', array('sesskey' => sesskey(), 'jobid' => $jobid, 'zip' => $zipfilename, 'type' => $plugintype)); redirect($nexturl); }
/** * Allocate submissions as requested by user * * @return workshop_allocation_result */ public function init() { global $PAGE; $mode = optional_param('mode', 'display', PARAM_ALPHA); $perpage = optional_param('perpage', null, PARAM_INT); if ($perpage and $perpage > 0 and $perpage <= 1000) { require_sesskey(); set_user_preference('workshopallocation_manual_perpage', $perpage); redirect($PAGE->url); } $result = new workshop_allocation_result($this); switch ($mode) { case 'new': if (!confirm_sesskey()) { throw new moodle_exception('confirmsesskeybad'); } $reviewerid = required_param('by', PARAM_INT); $authorid = required_param('of', PARAM_INT); $m = array(); // message object to be passed to the next page $submission = $this->workshop->get_submission_by_author($authorid); if (!$submission) { // nothing submitted by the given user $m[] = self::MSG_NOSUBMISSION; $m[] = $authorid; } else { // ok, we have the submission $res = $this->workshop->add_allocation($submission, $reviewerid); if ($res == workshop::ALLOCATION_EXISTS) { $m[] = self::MSG_EXISTS; $m[] = $submission->authorid; $m[] = $reviewerid; } else { $m[] = self::MSG_ADDED; $m[] = $submission->authorid; $m[] = $reviewerid; } } $m = implode('-', $m); // serialize message object to be passed via URL redirect($PAGE->url->out(false, array('m' => $m))); break; case 'del': if (!confirm_sesskey()) { throw new moodle_exception('confirmsesskeybad'); } $assessmentid = required_param('what', PARAM_INT); $confirmed = optional_param('confirm', 0, PARAM_INT); $assessment = $this->workshop->get_assessment_by_id($assessmentid); if ($assessment) { if (!$confirmed) { $m[] = self::MSG_CONFIRM_DEL; $m[] = $assessment->id; $m[] = $assessment->authorid; $m[] = $assessment->reviewerid; if (is_null($assessment->grade)) { $m[] = 0; } else { $m[] = 1; } } else { if ($this->workshop->delete_assessment($assessment->id)) { $m[] = self::MSG_DELETED; $m[] = $assessment->authorid; $m[] = $assessment->reviewerid; } else { $m[] = self::MSG_DELETE_ERROR; $m[] = $assessment->authorid; $m[] = $assessment->reviewerid; } } $m = implode('-', $m); // serialize message object to be passed via URL redirect($PAGE->url->out(false, array('m' => $m))); } break; } $result->set_status(workshop_allocation_result::STATUS_VOID); return $result; }
public function discsubscribers_action() { global $OUTPUT, $USER, $DB, $COURSE, $PAGE; require_once dirname(dirname(__DIR__)) . '/repository/discussion.php'; require_once dirname(dirname(__DIR__)) . '/lib/userselector/discussion/existing.php'; require_once dirname(dirname(__DIR__)) . '/lib/userselector/discussion/potential.php'; $discussionid = required_param('discussionid', PARAM_INT); $edit = optional_param('edit', -1, PARAM_BOOL); // Turn editing on and off. $url = $PAGE->url; $url->param('discussionid', $discussionid); if ($edit !== 0) { $url->param('edit', $edit); } $PAGE->set_url($url); $discussion = $DB->get_record('hsuforum_discussions', array('id' => $discussionid), '*', MUST_EXIST); $forum = $PAGE->activityrecord; $course = $COURSE; $cm = $PAGE->cm; $context = $PAGE->context; $repo = new \hsuforum_repository_discussion(); if (hsuforum_is_forcesubscribed($forum)) { throw new coding_exception('Cannot manage discussion subscriptions when subscription is forced'); } $currentgroup = groups_get_activity_group($cm); $options = array('forum' => $forum, 'discussion' => $discussion, 'currentgroup' => $currentgroup, 'context' => $context); $existingselector = new \hsuforum_userselector_discussion_existing('existingsubscribers', $options); $subscriberselector = new \hsuforum_userselector_discussion_potential('potentialsubscribers', $options); if (data_submitted()) { require_sesskey(); $subscribe = (bool) optional_param('subscribe', false, PARAM_RAW); $unsubscribe = (bool) optional_param('unsubscribe', false, PARAM_RAW); /** It has to be one or the other, not both or neither */ if (!($subscribe xor $unsubscribe)) { print_error('invalidaction'); } if ($subscribe) { $users = $subscriberselector->get_selected_users(); foreach ($users as $user) { $repo->subscribe($discussion->id, $user->id); } } else { if ($unsubscribe) { $users = $existingselector->get_selected_users(); foreach ($users as $user) { $repo->unsubscribe($discussion->id, $user->id); } } } $subscriberselector->invalidate_selected_users(); $existingselector->invalidate_selected_users(); redirect($PAGE->url); } $strsubscribers = get_string('discussionsubscribers', 'hsuforum'); // This works but it doesn't make a good navbar, would have to change the settings menu. // $PAGE->settingsnav->find('discsubscribers', navigation_node::TYPE_SETTING)->make_active(); $PAGE->navbar->add(shorten_text(format_string($discussion->name)), new moodle_url('/mod/hsuforum/discuss.php', array('d' => $discussion->id))); $PAGE->navbar->add($strsubscribers); $PAGE->set_title($strsubscribers); $PAGE->set_heading($COURSE->fullname); if (has_capability('mod/hsuforum:managesubscriptions', $context)) { if ($edit != -1) { $USER->subscriptionsediting = $edit; } if (!empty($USER->subscriptionsediting)) { $string = get_string('turneditingoff'); $edit = "off"; } else { $string = get_string('turneditingon'); $edit = "on"; } $url = $PAGE->url; $url->param('edit', $edit); $PAGE->set_button($OUTPUT->single_button($url, $string, 'get')); } else { unset($USER->subscriptionsediting); } $output = $OUTPUT->heading($strsubscribers); if (empty($USER->subscriptionsediting)) { $output .= $this->renderer->subscriber_overview($existingselector->get_repo()->get_subscribed_users($forum, $discussion, $context, $currentgroup), $discussion->name, $forum, $course); } else { $output .= $this->renderer->subscriber_selection_form($existingselector, $subscriberselector); } return $output; }
/** * save grade * * @param moodleform $mform * @return bool - was the grade saved */ private function process_save_grade(&$mform) { global $CFG; // Include grade form require_once($CFG->dirroot . '/mod/assign/gradeform.php'); // Need submit permission to submit an assignment require_capability('mod/assign:grade', $this->context); require_sesskey(); $rownum = required_param('rownum', PARAM_INT); $useridlist = optional_param('useridlist', '', PARAM_TEXT); if ($useridlist) { $useridlist = explode(',', $useridlist); } else { $useridlist = $this->get_grading_userid_list(); } $last = false; $userid = $useridlist[$rownum]; if ($rownum == count($useridlist) - 1) { $last = true; } $data = new stdClass(); $mform = new mod_assign_grade_form(null, array($this, $data, array('rownum'=>$rownum, 'useridlist'=>$useridlist, 'last'=>false)), 'post', '', array('class'=>'gradeform')); if ($formdata = $mform->get_data()) { if ($this->get_instance()->teamsubmission && $formdata->applytoall) { $groupid = 0; if ($this->get_submission_group($userid)) { $group = $this->get_submission_group($userid); if ($group) { $groupid = $group->id; } } $members = $this->get_submission_group_members($groupid, true); foreach ($members as $member) { // User may exist in multple groups (which should put them in the default group). $this->apply_grade_to_user($formdata, $member->id); } } else { $this->apply_grade_to_user($formdata, $userid); } } else { return false; } return true; }
/** * Add a new attempt for a user. * * @param int $userid int The user to add the attempt for * @return bool - true if successful. */ protected function process_add_attempt($userid) { require_capability('mod/assign:grade', $this->context); require_sesskey(); if ($this->get_instance()->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_NONE) { return false; } 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; } // No more than max attempts allowed. if ($this->get_instance()->maxattempts != ASSIGN_UNLIMITED_ATTEMPTS && $submission->attemptnumber >= ($this->get_instance()->maxattempts - 1)) { return false; } // Create the new submission record for the group/user. if ($this->get_instance()->teamsubmission) { $submission = $this->get_group_submission($userid, 0, true, $submission->attemptnumber+1); } else { $submission = $this->get_user_submission($userid, true, $submission->attemptnumber+1); } // Set the status of the new attempt to reopened. $submission->status = ASSIGN_SUBMISSION_STATUS_REOPENED; $this->update_submission($submission, $userid, false, $this->get_instance()->teamsubmission); return true; }
/** * Process the upload - creating the module in the course and returning the result to the browser * * @param string $displayname optional the name (from the browser) to give the course module instance * @param string $content optional the content of the upload (for non-file uploads) */ public function process($displayname = null, $content = null) { require_capability('moodle/course:manageactivities', $this->context); if ($this->is_file_upload()) { require_capability('moodle/course:managefiles', $this->context); if ($content != null) { throw new moodle_exception('fileuploadwithcontent', 'moodle'); } } else { if (empty($content)) { throw new moodle_exception('dnduploadwithoutcontent', 'moodle'); } } require_sesskey(); $this->displayname = $displayname; if ($this->is_file_upload()) { $this->handle_file_upload(); } else { $this->handle_other_upload($content); } }
/** * Loop through uploaded grades and update the grades for this assignment * * @param int $draftid - The unique draft item id for this import * @param int $importid - The unique import ID for this csv import operation * @param bool $ignoremodified - Ignore the last modified date when checking fields * @return string - The html response */ public function process_import_grades($draftid, $importid, $ignoremodified) { global $USER, $DB; require_sesskey(); require_capability('mod/assign:grade', $this->assignment->get_context()); $gradeimporter = new assignfeedback_offline_grade_importer($importid, $this->assignment); $context = context_user::instance($USER->id); $fs = get_file_storage(); if (!($files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false))) { redirect(new moodle_url('view.php', array('id' => $this->assignment->get_course_module()->id, 'action' => 'grading'))); return; } $file = reset($files); $csvdata = $file->get_content(); if ($csvdata) { $gradeimporter->parsecsv($csvdata); } if (!$gradeimporter->init()) { $thisurl = new moodle_url('/mod/assign/view.php', array('action' => 'viewpluginpage', 'pluginsubtype' => 'assignfeedback', 'plugin' => 'offline', 'pluginaction' => 'uploadgrades', 'id' => $assignment->get_course_module()->id)); print_error('invalidgradeimport', 'assignfeedback_offline', $thisurl); return; } // Does this assignment use a scale? $scaleoptions = null; if ($this->assignment->get_instance()->grade < 0) { if ($scale = $DB->get_record('scale', array('id' => -$this->assignment->get_instance()->grade))) { $scaleoptions = make_menu_from_list($scale->scale); } } // We may need to upgrade the gradebook comments after this update. $adminconfig = $this->assignment->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; $updatecount = 0; while ($record = $gradeimporter->next()) { $user = $record->user; $modified = $record->modified; $userdesc = fullname($user); $usergrade = $this->assignment->get_user_grade($user->id, false); if (!empty($scaleoptions)) { // This is a scale - we need to convert any grades to indexes in the scale. $scaleindex = array_search($record->grade, $scaleoptions); if ($scaleindex !== false) { $record->grade = $scaleindex; } else { $record->grade = ''; } } else { $record->grade = unformat_float($record->grade); } // Note: Do not count the seconds when comparing modified dates. $skip = false; $stalemodificationdate = $usergrade && $usergrade->timemodified > $modified + 60; if ($usergrade && $usergrade->grade == $record->grade) { // Skip - grade not modified. $skip = true; } else { if (!isset($record->grade) || $record->grade === '' || $record->grade < 0) { // Skip - grade has no value. $skip = true; } else { if (!$ignoremodified && $stalemodificationdate) { // Skip - grade has been modified. $skip = true; } else { if ($this->assignment->grading_disabled($record->user->id)) { // Skip grade is locked. $skip = true; } else { if ($this->assignment->get_instance()->grade > -1 && ($record->grade < 0 || $record->grade > $this->assignment->get_instance()->grade)) { // Out of range. $skip = true; } } } } } if (!$skip) { $grade = $this->assignment->get_user_grade($record->user->id, true); $grade->grade = $record->grade; $grade->grader = $USER->id; if ($this->assignment->update_grade($grade)) { $this->assignment->notify_grade_modified($grade); $updatecount += 1; } } if ($ignoremodified || !$stalemodificationdate) { foreach ($record->feedback as $feedback) { $plugin = $feedback['plugin']; $field = $feedback['field']; $newvalue = $feedback['value']; $description = $feedback['description']; $oldvalue = ''; if ($usergrade) { $oldvalue = $plugin->get_editor_text($field, $usergrade->id); if (empty($oldvalue)) { $oldvalue = ''; } } if ($newvalue != $oldvalue) { $updatecount += 1; $grade = $this->assignment->get_user_grade($record->user->id, true); $this->assignment->notify_grade_modified($grade); $plugin->set_editor_text($field, $newvalue, $grade->id); // If this is the gradebook comments plugin - post an update to the gradebook. if ($plugin->get_subtype() . '_' . $plugin->get_type() == $gradebookplugin) { $grade->feedbacktext = $plugin->text_for_gradebook($grade); $grade->feedbackformat = $plugin->format_for_gradebook($grade); $this->assignment->update_grade($grade); } } } } } $gradeimporter->close(true); $renderer = $this->assignment->get_renderer(); $o = ''; $o .= $renderer->render(new assign_header($this->assignment->get_instance(), $this->assignment->get_context(), false, $this->assignment->get_course_module()->id, get_string('importgrades', 'assignfeedback_offline'))); $o .= $renderer->box(get_string('updatedgrades', 'assignfeedback_offline', $updatecount)); $url = new moodle_url('view.php', array('id' => $this->assignment->get_course_module()->id, 'action' => 'grading')); $o .= $renderer->continue_button($url); $o .= $renderer->render_footer(); return $o; }
public function check_answer() { global $CFG, $PAGE; $formattextdefoptions = new stdClass(); $formattextdefoptions->noclean = true; $formattextdefoptions->para = false; $result = parent::check_answer(); $mform = $this->make_answer_form(); $data = $mform->get_data(); require_sesskey(); if (!$data) { redirect(new moodle_url('/mod/lesson/view.php', array('id' => $PAGE->cm->id, 'pageid' => $this->properties->id))); } $response = $data->response; $getanswers = $this->get_answers(); foreach ($getanswers as $key => $answer) { $getanswers[$key] = parent::rewrite_answers_urls($answer); } $correct = array_shift($getanswers); $wrong = array_shift($getanswers); $answers = array(); foreach ($getanswers as $key => $answer) { if ($answer->answer !== '' or $answer->response !== '') { $answers[$answer->id] = $answer; } } // get the user's exact responses for record keeping $hits = 0; $userresponse = array(); foreach ($response as $id => $value) { if ($value == '') { $result->noanswer = true; return $result; } $value = htmlspecialchars_decode($value); $userresponse[] = $value; // Make sure the user's answer exists in question's answer if (array_key_exists($id, $answers)) { $answer = $answers[$id]; $result->studentanswer .= '<br />' . format_text($answer->answer, $answer->answerformat, $formattextdefoptions) . ' = ' . $value; if (trim($answer->response) == trim($value)) { $hits++; } } } $result->userresponse = implode(",", $userresponse); if ($hits == count($answers)) { $result->correctanswer = true; $result->response = format_text($correct->answer, $correct->answerformat, $formattextdefoptions); $result->answerid = $correct->id; $result->newpageid = $correct->jumpto; } else { $result->correctanswer = false; $result->response = format_text($wrong->answer, $wrong->answerformat, $formattextdefoptions); $result->answerid = $wrong->id; $result->newpageid = $wrong->jumpto; } return $result; }
/** * Displays the report. */ function display($quiz, $cm, $course) { global $CFG, $QTYPES; $viewoptions = array('mode' => 'grading', 'q' => $quiz->id); if ($questionid = optional_param('questionid', 0, PARAM_INT)) { $viewoptions += array('questionid' => $questionid); } // grade question specific parameters $gradeungraded = optional_param('gradeungraded', 0, PARAM_INT); if ($userid = optional_param('userid', 0, PARAM_INT)) { $viewoptions += array('userid' => $userid); } if ($attemptid = optional_param('attemptid', 0, PARAM_INT)) { $viewoptions += array('attemptid' => $attemptid); } if ($gradeall = optional_param('gradeall', 0, PARAM_INT)) { $viewoptions += array('gradeall' => $gradeall); } if ($gradeungraded = optional_param('gradeungraded', 0, PARAM_INT)) { $viewoptions += array('gradeungraded' => $gradeungraded); } if ($gradenextungraded = optional_param('gradenextungraded', 0, PARAM_INT)) { $viewoptions += array('gradenextungraded' => $gradenextungraded); } $this->cm = $cm; $this->print_header_and_tabs($cm, $course, $quiz, $reportmode = "grading"); // Check permissions $this->context = get_context_instance(CONTEXT_MODULE, $cm->id); if (!has_capability('mod/quiz:grade', $this->context)) { notify(get_string('gradingnotallowed', 'quiz_grading')); return true; } $gradeableqs = quiz_report_load_questions($quiz); $questionsinuse = implode(',', array_keys($gradeableqs)); foreach ($gradeableqs as $qid => $question) { if (!$QTYPES[$question->qtype]->is_question_manual_graded($question, $questionsinuse)) { unset($gradeableqs[$qid]); } } if (empty($gradeableqs)) { print_heading(get_string('noessayquestionsfound', 'quiz')); return true; } else { if (count($gradeableqs) == 1) { $questionid = array_shift(array_keys($gradeableqs)); } } $currentgroup = groups_get_activity_group($this->cm, true); $this->users = get_users_by_capability($this->context, array('mod/quiz:reviewmyattempts', 'mod/quiz:attempt'), '', '', '', '', $currentgroup, '', false); $this->userids = implode(',', array_keys($this->users)); if (!empty($questionid)) { if (!isset($gradeableqs[$questionid])) { error("Gradeable question with id {$questionid} not found"); } else { $question =& $gradeableqs[$questionid]; } $question->maxgrade = get_field('quiz_question_instances', 'grade', 'quiz', $quiz->id, 'question', $question->id); // Some of the questions code is optimised to work with several questions // at once so it wants the question to be in an array. The array key // must be the question id. $key = $question->id; $questions[$key] =& $question; // We need to add additional questiontype specific information to // the question objects. if (!get_question_options($questions)) { error("Unable to load questiontype specific question information"); } // This will have extended the question object so that it now holds // all the information about the questions that may be needed later. } add_to_log($course->id, "quiz", "manualgrading", "report.php?mode=grading&q={$quiz->id}", "{$quiz->id}", "{$cm->id}"); echo '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // for overlib if ($data = data_submitted()) { // post data submitted, process it require_sesskey(); // now go through all of the responses and save them. $allok = true; foreach ($data->manualgrades as $uniqueid => $response) { // get our attempt $uniqueid = clean_param($uniqueid, PARAM_INT); if (!($attempt = get_record_sql("SELECT * FROM {$CFG->prefix}quiz_attempts " . "WHERE uniqueid = {$uniqueid} AND " . "userid IN ({$this->userids}) AND " . "quiz=" . $quiz->id))) { error('No such attempt ID exists'); } // Load the state for this attempt (The questions array was created earlier) $states = get_question_states($questions, $quiz, $attempt); // The $states array is indexed by question id but because we are dealing // with only one question there is only one entry in this array $state =& $states[$question->id]; // the following will update the state and attempt $error = question_process_comment($question, $state, $attempt, $response['comment'], $response['grade']); if (is_string($error)) { notify($error); $allok = false; } else { if ($state->changed) { // If the state has changed save it and update the quiz grade save_question_session($question, $state); quiz_save_best_grade($quiz, $attempt->userid); } } } if ($allok) { notify(get_string('changessaved', 'quiz'), 'notifysuccess'); } else { notify(get_string('changessavedwitherrors', 'quiz'), 'notifysuccess'); } } $this->viewurl = new moodle_url($CFG->wwwroot . '/mod/quiz/report.php', $viewoptions); /// find out current groups mode if ($groupmode = groups_get_activity_groupmode($this->cm)) { // Groups are being used groups_print_activity_menu($this->cm, $this->viewurl->out(false, array('userid' => 0, 'attemptid' => 0))); } echo '<div class="quizattemptcounts">' . quiz_num_attempt_summary($quiz, $cm, true, $currentgroup) . '</div>'; if (empty($this->users)) { if ($currentgroup) { notify(get_string('nostudentsingroup')); } else { notify(get_string('nostudentsyet')); } return true; } $gradeablequestionids = implode(',', array_keys($gradeableqs)); $qattempts = quiz_get_total_qas_graded_and_ungraded($quiz, $gradeablequestionids, $this->userids); if (empty($qattempts)) { notify(get_string('noattemptstoshow', 'quiz')); return true; } $qmenu = array(); foreach ($gradeableqs as $qid => $questionformenu) { $a = new object(); $a->number = $gradeableqs[$qid]->number; $a->name = $gradeableqs[$qid]->name; $a->gradedattempts = $qattempts[$qid]->gradedattempts; $a->totalattempts = $qattempts[$qid]->totalattempts; $a->openspan = ''; $a->closespan = ''; $qmenu[$qid] = get_string('questiontitle', 'quiz_grading', $a); } if (count($gradeableqs) != 1) { $qurl = fullclone($this->viewurl); $qurl->remove_params('questionid', 'attemptid', 'gradeall', 'gradeungraded', 'gradenextungraded'); $menu = popup_form($qurl->out() . '&questionid=', $qmenu, 'questionid', $questionid, 'choose', '', '', true); echo '<div class="mdl-align">' . $menu . '</div>'; } if (!$questionid) { return true; } $a = new object(); $a->number = $question->number; $a->name = $question->name; $a->gradedattempts = $qattempts[$question->id]->gradedattempts; $a->totalattempts = $qattempts[$question->id]->totalattempts; $a->openspan = '<span class="highlightgraded">'; $a->closespan = '</span>'; print_heading(get_string('questiontitle', 'quiz_grading', $a)); // our 3 different views // the first one displays all of the manually graded questions in the quiz // with the number of ungraded attempts for each question // the second view displays the users who have answered the essay question // and all of their attempts at answering the question // the third prints the question with a comment // and grade form underneath it $ungraded = $qattempts[$questionid]->totalattempts - $qattempts[$questionid]->gradedattempts; if ($gradenextungraded || $gradeungraded || $gradeall || $userid || $attemptid) { $this->print_questions_and_form($quiz, $question, $userid, $attemptid, $gradeungraded, $gradenextungraded, $ungraded); } else { $this->view_question($quiz, $question, $qattempts[$questionid]->totalattempts, $ungraded); } return true; }
public function check_answer() { global $CFG; $result = parent::check_answer(); $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot . '/mod/lesson/continue.php', array('contents' => $this->get_contents())); $data = $mform->get_data(); require_sesskey(); $studentanswer = trim($data->answer); if ($studentanswer === '') { $result->noanswer = true; return $result; } $i = 0; $answers = $this->get_answers(); foreach ($answers as $answer) { $answer = parent::rewrite_answers_urls($answer, false); $i++; // Applying PARAM_TEXT as it is applied to the answer submitted by the user. $expectedanswer = clean_param($answer->answer, PARAM_TEXT); $ismatch = false; $markit = false; $useregexp = $this->qoption; if ($useregexp) { //we are using 'normal analysis', which ignores case $ignorecase = ''; if (substr($expectedanswer, -2) == '/i') { $expectedanswer = substr($expectedanswer, 0, -2); $ignorecase = 'i'; } } else { $expectedanswer = str_replace('*', '#####', $expectedanswer); $expectedanswer = preg_quote($expectedanswer, '/'); $expectedanswer = str_replace('#####', '.*', $expectedanswer); } // see if user typed in any of the correct answers if (!$this->lesson->custom && $this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) or $this->lesson->custom && $answer->score > 0) { if (!$useregexp) { // we are using 'normal analysis', which ignores case if (preg_match('/^' . $expectedanswer . '$/i', $studentanswer)) { $ismatch = true; } } else { if (preg_match('/^' . $expectedanswer . '$/' . $ignorecase, $studentanswer)) { $ismatch = true; } } if ($ismatch == true) { $result->correctanswer = true; } } else { if (!$useregexp) { //we are using 'normal analysis' // see if user typed in any of the wrong answers; don't worry about case if (preg_match('/^' . $expectedanswer . '$/i', $studentanswer)) { $ismatch = true; } } else { // we are using regular expressions analysis $startcode = substr($expectedanswer, 0, 2); switch ($startcode) { //1- check for absence of required string in $studentanswer (coded by initial '--') case "--": $expectedanswer = substr($expectedanswer, 2); if (!preg_match('/^' . $expectedanswer . '$/' . $ignorecase, $studentanswer)) { $ismatch = true; } break; //2- check for code for marking wrong strings (coded by initial '++') //2- check for code for marking wrong strings (coded by initial '++') case "++": $expectedanswer = substr($expectedanswer, 2); $markit = true; //check for one or several matches if (preg_match_all('/' . $expectedanswer . '/' . $ignorecase, $studentanswer, $matches)) { $ismatch = true; $nb = count($matches[0]); $original = array(); $marked = array(); $fontStart = '<span class="incorrect matches">'; $fontEnd = '</span>'; for ($i = 0; $i < $nb; $i++) { array_push($original, $matches[0][$i]); array_push($marked, $fontStart . $matches[0][$i] . $fontEnd); } $studentanswer = str_replace($original, $marked, $studentanswer); } break; //3- check for wrong answers belonging neither to -- nor to ++ categories //3- check for wrong answers belonging neither to -- nor to ++ categories default: if (preg_match('/^' . $expectedanswer . '$/' . $ignorecase, $studentanswer, $matches)) { $ismatch = true; } break; } $result->correctanswer = false; } } if ($ismatch) { $result->newpageid = $answer->jumpto; $options = new stdClass(); $options->para = false; $result->response = format_text($answer->response, $answer->responseformat, $options); $result->answerid = $answer->id; break; // quit answer analysis immediately after a match has been found } } $result->userresponse = $studentanswer; //clean student answer as it goes to output. $result->studentanswer = s($studentanswer); return $result; }
public function construction_override($pageid, lesson $lesson) { global $DB, $CFG, $PAGE; require_sesskey(); // first get the preceeding page $timenow = time(); // the new page is not the first page (end of branch always comes after an existing page) if (!($page = $DB->get_record("lesson_pages", array("id" => $pageid)))) { print_error('cannotfindpagerecord', 'lesson'); } // chain back up to find the (nearest branch table) $btpage = clone $page; $btpageid = $btpage->id; while ($btpage->qtype != LESSON_PAGE_BRANCHTABLE && $btpage->prevpageid > 0) { $btpageid = $btpage->prevpageid; if (!($btpage = $DB->get_record("lesson_pages", array("id" => $btpageid)))) { print_error('cannotfindpagerecord', 'lesson'); } } if ($btpage->qtype == LESSON_PAGE_BRANCHTABLE) { $newpage = new stdClass(); $newpage->lessonid = $lesson->id; $newpage->prevpageid = $pageid; $newpage->nextpageid = $page->nextpageid; $newpage->qtype = $this->qtype; $newpage->timecreated = $timenow; $newpage->title = get_string("endofbranch", "lesson"); $newpage->contents = get_string("endofbranch", "lesson"); $newpageid = $DB->insert_record("lesson_pages", $newpage); // update the linked list... $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); if ($page->nextpageid) { // the new page is not the last page $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); } // ..and the single "answer" $newanswer = new stdClass(); $newanswer->lessonid = $lesson->id; $newanswer->pageid = $newpageid; $newanswer->timecreated = $timenow; $newanswer->jumpto = $btpageid; $newanswerid = $DB->insert_record("lesson_answers", $newanswer); $lesson->add_message(get_string('addedanendofbranch', 'lesson'), 'notifysuccess'); } else { $lesson->add_message(get_string('nobranchtablefound', 'lesson')); } redirect($CFG->wwwroot . "/mod/lesson/edit.php?id=" . $PAGE->cm->id); }
public function check_answer() { global $PAGE, $CFG; $result = parent::check_answer(); $result->isessayquestion = true; $mform = new lesson_display_answer_form_essay($CFG->wwwroot . '/mod/lesson/continue.php', array('contents' => $this->get_contents())); $data = $mform->get_data(); require_sesskey(); if (!$data) { redirect(new moodle_url('/mod/lesson/view.php', array('id' => $PAGE->cm->id, 'pageid' => $this->properties->id))); } if (is_array($data->answer)) { $studentanswer = $data->answer['text']; $studentanswerformat = $data->answer['format']; } else { $studentanswer = $data->answer; $studentanswerformat = FORMAT_MOODLE; } if (trim($studentanswer) === '') { $result->noanswer = true; return $result; } $answers = $this->get_answers(); foreach ($answers as $answer) { $result->answerid = $answer->id; $result->newpageid = $answer->jumpto; } $userresponse = new stdClass(); $userresponse->sent = 0; $userresponse->graded = 0; $userresponse->score = 0; $userresponse->answer = $studentanswer; $userresponse->answerformat = $studentanswerformat; $userresponse->response = ""; $result->userresponse = serialize($userresponse); $result->studentanswerformat = $studentanswerformat; $result->studentanswer = $studentanswer; return $result; }
public function check_answer() { global $DB, $CFG, $PAGE; $result = parent::check_answer(); $formattextdefoptions = new stdClass(); $formattextdefoptions->noclean = true; $formattextdefoptions->para = false; $answers = $this->get_used_answers(); shuffle($answers); $action = $CFG->wwwroot . '/mod/lesson/continue.php'; $params = array('answers' => $answers, 'lessonid' => $this->lesson->id, 'contents' => $this->get_contents()); if ($this->properties->qoption) { $mform = new lesson_display_answer_form_multichoice_multianswer($action, $params); } else { $mform = new lesson_display_answer_form_multichoice_singleanswer($action, $params); } $data = $mform->get_data(); require_sesskey(); if (!$data) { redirect(new moodle_url('/mod/lesson/view.php', array('id' => $PAGE->cm->id, 'pageid' => $this->properties->id))); } if ($this->properties->qoption) { // MULTIANSWER allowed, user's answer is an array if (empty($data->answer) || !is_array($data->answer)) { $result->noanswer = true; return $result; } $studentanswers = array(); foreach ($data->answer as $key => $value) { $studentanswers[] = (int) $key; } // get what the user answered $result->userresponse = implode(",", $studentanswers); // get the answers in a set order, the id order $answers = $this->get_used_answers(); $ncorrect = 0; $nhits = 0; $correctresponse = ''; $wrongresponse = ''; $correctanswerid = 0; $wronganswerid = 0; // store student's answers for displaying on feedback page $result->studentanswer = ''; foreach ($answers as $answer) { foreach ($studentanswers as $answerid) { if ($answerid == $answer->id) { $result->studentanswer .= '<br />' . format_text($answer->answer, $answer->answerformat, $formattextdefoptions); } } } $correctpageid = null; $wrongpageid = null; // this is for custom scores. If score on answer is positive, it is correct if ($this->lesson->custom) { $ncorrect = 0; $nhits = 0; foreach ($answers as $answer) { if ($answer->score > 0) { $ncorrect++; foreach ($studentanswers as $answerid) { if ($answerid == $answer->id) { $nhits++; } } // save the first jumpto page id, may be needed!... if (!isset($correctpageid)) { // leave in its "raw" state - will converted into a proper page id later $correctpageid = $answer->jumpto; } // save the answer id for scoring if ($correctanswerid == 0) { $correctanswerid = $answer->id; } // ...also save any response from the correct answers... if (trim(strip_tags($answer->response))) { $correctresponse = format_text($answer->response, $answer->responseformat, $formattextdefoptions); } } else { // save the first jumpto page id, may be needed!... if (!isset($wrongpageid)) { // leave in its "raw" state - will converted into a proper page id later $wrongpageid = $answer->jumpto; } // save the answer id for scoring if ($wronganswerid == 0) { $wronganswerid = $answer->id; } // ...and from the incorrect ones, don't know which to use at this stage if (trim(strip_tags($answer->response))) { $wrongresponse = format_text($answer->response, $answer->responseformat, $formattextdefoptions); } } } } else { foreach ($answers as $answer) { if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { $ncorrect++; foreach ($studentanswers as $answerid) { if ($answerid == $answer->id) { $nhits++; } } // save the first jumpto page id, may be needed!... if (!isset($correctpageid)) { // leave in its "raw" state - will converted into a proper page id later $correctpageid = $answer->jumpto; } // save the answer id for scoring if ($correctanswerid == 0) { $correctanswerid = $answer->id; } // ...also save any response from the correct answers... if (trim(strip_tags($answer->response))) { $correctresponse = format_text($answer->response, $answer->responseformat, $formattextdefoptions); } } else { // save the first jumpto page id, may be needed!... if (!isset($wrongpageid)) { // leave in its "raw" state - will converted into a proper page id later $wrongpageid = $answer->jumpto; } // save the answer id for scoring if ($wronganswerid == 0) { $wronganswerid = $answer->id; } // ...and from the incorrect ones, don't know which to use at this stage if (trim(strip_tags($answer->response))) { $wrongresponse = format_text($answer->response, $answer->responseformat, $formattextdefoptions); } } } } if (count($studentanswers) == $ncorrect and $nhits == $ncorrect) { $result->correctanswer = true; $result->response = $correctresponse; $result->newpageid = $correctpageid; $result->answerid = $correctanswerid; } else { $result->response = $wrongresponse; $result->newpageid = $wrongpageid; $result->answerid = $wronganswerid; } } else { // only one answer allowed if (empty($data->answerid) && !is_int($data->answerid)) { $result->noanswer = true; return $result; } $result->answerid = $data->answerid; if (!($answer = $DB->get_record("lesson_answers", array("id" => $result->answerid)))) { print_error("Continue: answer record not found"); } if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { $result->correctanswer = true; } if ($this->lesson->custom) { if ($answer->score > 0) { $result->correctanswer = true; } else { $result->correctanswer = false; } } $result->newpageid = $answer->jumpto; $result->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); $result->userresponse = format_text($answer->answer, $answer->answerformat, $formattextdefoptions); $result->studentanswer = $result->userresponse; } return $result; }
} $edit = ($editable and $edit); $seenaspublished = false; // is the submission seen as a published submission? if ($submission->id and ($ownsubmission or $canviewall or $isreviewer)) { // ok you can go } elseif ($submission->id and $ispublished) { // ok you can go $seenaspublished = true; } elseif (is_null($submission->id) and $cansubmit) { // ok you can go } else { print_error('nopermissions', 'error', $workshop->view_url(), 'view or create submission'); } if ($assess and $submission->id and !$isreviewer and $canallocate and $workshop->assessing_allowed($USER->id)) { require_sesskey(); $assessmentid = $workshop->add_allocation($submission, $USER->id); redirect($workshop->assess_url($assessmentid)); } if ($edit) { require_once dirname(__FILE__) . '/submission_form.php'; $maxfiles = $workshop->nattachments; $maxbytes = $workshop->maxbytes; $contentopts = array('trusttext' => true, 'subdirs' => false, 'maxfiles' => $maxfiles, 'maxbytes' => $maxbytes, 'context' => $workshop->context, 'return_types' => FILE_INTERNAL | FILE_EXTERNAL); $attachmentopts = array('subdirs' => true, 'maxfiles' => $maxfiles, 'maxbytes' => $maxbytes, 'return_types' => FILE_INTERNAL); $submission = file_prepare_standard_editor($submission, 'content', $contentopts, $workshop->context, 'mod_workshop', 'submission_content', $submission->id); $submission = file_prepare_standard_filemanager($submission, 'attachment', $attachmentopts, $workshop->context, 'mod_workshop', 'submission_attachment', $submission->id); $mform = new workshop_submission_form($PAGE->url, array('current' => $submission, 'workshop' => $workshop, 'contentopts' => $contentopts, 'attachmentopts' => $attachmentopts)); if ($mform->is_cancelled()) { redirect($workshop->view_url()); } elseif ($cansubmit and $formdata = $mform->get_data()) {
/** * Delete the step. * * @param int $stepid The ID of the step to remove. */ protected function delete_step($stepid) { require_sesskey(); $step = step::instance($stepid); $tour = $step->get_tour(); $step->remove(); redirect($tour->get_view_link()); }