/** * Checks whether the current user is permitted (using the normal UI) to * remove a specific group member, assuming that they have access to remove * group members in general. * * For automatically-created group member entries, this checks with the * relevant plugin to see whether it is permitted. The default, if the plugin * doesn't provide a function, is true. * * For other entries (and any which have already been deleted/don't exist) it * just returns true. * * @param mixed $grouporid The group id or group object * @param mixed $userorid The user id or user object * @return bool True if permitted, false otherwise */ function groups_remove_member_allowed($grouporid, $userorid) { global $DB; if (is_object($userorid)) { $userid = $userorid->id; } else { $userid = $userorid; } if (is_object($grouporid)) { $groupid = $grouporid->id; } else { $groupid = $grouporid; } // Get entry if (!($entry = $DB->get_record('groups_members', array('groupid' => $groupid, 'userid' => $userid), '*', IGNORE_MISSING))) { // If the entry does not exist, they are allowed to remove it (this // is consistent with groups_remove_member below). return true; } // If the entry does not have a component value, they can remove it if (empty($entry->component)) { return true; } // It has a component value, so we need to call a plugin function (if it // exists); the default is to allow removal return component_callback($entry->component, 'allow_group_member_remove', array($entry->itemid, $entry->groupid, $entry->userid), true); }
function lti_get_types() { global $OUTPUT; $subtypes = array(); foreach (get_plugin_list('ltisource') as $name => $dir) { if ($moretypes = component_callback("ltisource_{$name}", 'get_types')) { $subtypes = array_merge($subtypes, $moretypes); } } if (empty($subtypes)) { return MOD_SUBTYPE_NO_CHILDREN; } $types = array(); $type = new stdClass(); $type->modclass = MOD_CLASS_ACTIVITY; $type->type = 'lti_group_start'; $type->typestr = '--' . get_string('modulenameplural', 'mod_lti'); $types[] = $type; $link = get_string('modulename_link', 'mod_lti'); $linktext = get_string('morehelp'); $help = get_string('modulename_help', 'mod_lti'); $help .= html_writer::tag('div', $OUTPUT->doc_link($link, $linktext, true), array('class' => 'helpdoclink')); $type = new stdClass(); $type->modclass = MOD_CLASS_ACTIVITY; $type->type = ''; $type->typestr = get_string('generaltool', 'mod_lti'); $type->help = $help; $types[] = $type; $types = array_merge($types, $subtypes); $type = new stdClass(); $type->modclass = MOD_CLASS_ACTIVITY; $type->type = 'lti_group_end'; $type->typestr = '--'; $types[] = $type; return $types; }
list($context, $course, $cm) = get_context_info_array($contextid); require_login($course, false, $cm); $url = new moodle_url('/rating/index.php', array('contextid' => $contextid, 'component' => $component, 'ratingarea' => $ratingarea, 'itemid' => $itemid, 'scaleid' => $scaleid)); if (!empty($sort)) { $url->param('sort', $sort); } if (!empty($popup)) { $url->param('popup', $popup); } $PAGE->set_url($url); $PAGE->set_context($context); if ($popup) { $PAGE->set_pagelayout('popup'); } $params = array('contextid' => $contextid, 'component' => $component, 'ratingarea' => $ratingarea, 'itemid' => $itemid, 'scaleid' => $scaleid); if (!has_capability('moodle/rating:view', $context) || !component_callback($component, 'rating_can_see_item_ratings', array($params), true)) { print_error('noviewrate', 'rating'); } $canviewallratings = has_capability('moodle/rating:viewall', $context); switch ($sort) { case 'firstname': $sqlsort = "u.firstname ASC"; break; case 'rating': $sqlsort = "r.rating ASC"; break; default: $sqlsort = "r.timemodified ASC"; } $scalemenu = make_grades_menu($scaleid); $strrating = get_string('rating', 'rating');
/** * Get a list of reports that support the given store instance. * * @param string $logstore Name of the store. * * @return array List of supported reports */ public function get_supported_reports($logstore) { $allstores = self::get_store_plugins(); if (empty($allstores[$logstore])) { // Store doesn't exist. return array(); } $reports = get_plugin_list_with_function('report', 'supports_logstore', 'lib.php'); $enabled = $this->stores; if (empty($enabled[$logstore])) { // Store is not enabled, init an instance. $classname = '\\' . $logstore . '\\log\\store'; $instance = new $classname($this); } else { $instance = $enabled[$logstore]; } $return = array(); foreach ($reports as $report => $fulldir) { if (component_callback($report, 'supports_logstore', array($instance), false)) { $return[$report] = get_string('pluginname', $report); } } return $return; }
/** * Set the visibility of a module and inherent properties. * * Note: Do not forget to trigger the event \core\event\course_module_updated as it needs * to be triggered manually, refer to {@link \core\event\course_module_updated::create_from_cm()}. * * From 2.4 the parameter $prevstateoverrides has been removed, the logic it triggered * has been moved to {@link set_section_visible()} which was the only place from which * the parameter was used. * * @param int $id of the module * @param int $visible state of the module * @return bool false when the module was not found, true otherwise */ function set_coursemodule_visible($id, $visible) { global $DB, $CFG; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/calendar/lib.php'; // Trigger developer's attention when using the previously removed argument. if (func_num_args() > 2) { debugging('Wrong number of arguments passed to set_coursemodule_visible(), $prevstateoverrides has been removed.', DEBUG_DEVELOPER); } if (!($cm = $DB->get_record('course_modules', array('id' => $id)))) { return false; } // Create events and propagate visibility to associated grade items if the value has changed. // Only do this if it's changed to avoid accidently overwriting manual showing/hiding of student grades. if ($cm->visible == $visible) { return true; } if (!($modulename = $DB->get_field('modules', 'name', array('id' => $cm->module)))) { return false; } if ($events = $DB->get_records('event', array('instance' => $cm->instance, 'modulename' => $modulename))) { foreach ($events as $event) { if ($visible) { $event = new calendar_event($event); $event->toggle_visibility(true); } else { $event = new calendar_event($event); $event->toggle_visibility(false); } } } // Updating visible and visibleold to keep them in sync. Only changing a section visibility will // affect visibleold to allow for an original visibility restore. See set_section_visible(). $cminfo = new stdClass(); $cminfo->id = $id; $cminfo->visible = $visible; $cminfo->visibleold = $visible; $DB->update_record('course_modules', $cminfo); // Hide the associated grade items so the teacher doesn't also have to go to the gradebook and hide them there. // Note that this must be done after updating the row in course_modules, in case // the modules grade_item_update function needs to access $cm->visible. if (plugin_supports('mod', $modulename, FEATURE_CONTROLS_GRADE_VISIBILITY) && component_callback_exists('mod_' . $modulename, 'grade_item_update')) { $instance = $DB->get_record($modulename, array('id' => $cm->instance), '*', MUST_EXIST); component_callback('mod_' . $modulename, 'grade_item_update', array($instance)); } else { $grade_items = grade_item::fetch_all(array('itemtype' => 'mod', 'itemmodule' => $modulename, 'iteminstance' => $cm->instance, 'courseid' => $cm->course)); if ($grade_items) { foreach ($grade_items as $grade_item) { $grade_item->set_hidden(!$visible); } } } rebuild_course_cache($cm->course, true); return true; }
public function get_mod_recent_activity($context) { global $COURSE, $OUTPUT; $viewfullnames = has_capability('moodle/site:viewfullnames', $context); $recentactivity = array(); $timestart = time() - 86400 * 7; // 7 days ago. if (optional_param('testing', false, PARAM_BOOL)) { $timestart = time() - 86400 * 700; // 700 days ago for testing purposes. } $modinfo = get_fast_modinfo($COURSE); $usedmodules = $modinfo->get_used_module_names(); if (empty($usedmodules)) { // No used modules so return null string. return ''; } foreach ($usedmodules as $modname => $modfullname) { // Each module gets it's own logs and prints them. ob_start(); $hascontent = component_callback('mod_' . $modname, 'print_recent_activity', array($COURSE, $viewfullnames, $timestart), false); if ($hascontent) { $content = ob_get_contents(); if (!empty($content)) { $recentactivity[$modname] = $content; } } ob_end_clean(); } $output = ''; if (!empty($recentactivity)) { foreach ($recentactivity as $modname => $moduleactivity) { // Get mod icon, empty alt as title already there. $img = html_writer::tag('img', '', array('src' => $OUTPUT->pix_url('icon', $modname), 'alt' => '')); // Create media object for module activity. $output .= "<div class='snap-media-object course-footer-update-{$modname}'>{$img}" . "<div class=snap-media-body>{$moduleactivity}</div></div>"; } } return $output; }
public function definition() { global $PAGE, $OUTPUT, $COURSE; if ($type = optional_param('type', false, PARAM_ALPHA)) { component_callback("ltisource_{$type}", 'add_instance_hook'); } $this->typeid = 0; $mform =& $this->_form; // Adding the "general" fieldset, where all the common settings are shown. $mform->addElement('header', 'general', get_string('general', 'form')); // Adding the standard "name" field. $mform->addElement('text', 'name', get_string('basicltiname', 'lti'), array('size' => '64')); $mform->setType('name', PARAM_TEXT); $mform->addRule('name', null, 'required', null, 'client'); $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); // Adding the optional "intro" and "introformat" pair of fields. $this->standard_intro_elements(get_string('basicltiintro', 'lti')); $mform->setAdvanced('introeditor'); // Display the label to the right of the checkbox so it looks better & matches rest of the form. if ($mform->elementExists('showdescription')) { $coursedesc = $mform->getElement('showdescription'); if (!empty($coursedesc)) { $coursedesc->setText(' ' . $coursedesc->getLabel()); $coursedesc->setLabel(' '); } } $mform->setAdvanced('showdescription'); $mform->addElement('checkbox', 'showtitlelaunch', ' ', ' ' . get_string('display_name', 'lti')); $mform->setAdvanced('showtitlelaunch'); $mform->setDefault('showtitlelaunch', true); $mform->addHelpButton('showtitlelaunch', 'display_name', 'lti'); $mform->addElement('checkbox', 'showdescriptionlaunch', ' ', ' ' . get_string('display_description', 'lti')); $mform->setAdvanced('showdescriptionlaunch'); $mform->addHelpButton('showdescriptionlaunch', 'display_description', 'lti'); // Tool settings. $attributes = array(); if ($update = optional_param('update', false, PARAM_INT)) { $attributes['disabled'] = 'disabled'; } $attributes['class'] = 'lti_contentitem'; $tooltypes = $mform->addElement('select', 'typeid', get_string('external_tool_type', 'lti'), array(), $attributes); $typeid = optional_param('typeid', false, PARAM_INT); $mform->getElement('typeid')->setValue($typeid); $mform->addHelpButton('typeid', 'external_tool_type', 'lti'); $toolproxy = array(); // Array of tool type IDs that don't support ContentItemSelectionRequest. $noncontentitemtypes = []; foreach (lti_get_types_for_add_instance() as $id => $type) { if (!empty($type->toolproxyid)) { $toolproxy[] = $type->id; $attributes = array('globalTool' => 1, 'toolproxy' => 1); $enabledcapabilities = explode("\n", $type->enabledcapability); if (!in_array('Result.autocreate', $enabledcapabilities)) { $attributes['nogrades'] = 1; } if (!in_array('Person.name.full', $enabledcapabilities) && !in_array('Person.name.family', $enabledcapabilities) && !in_array('Person.name.given', $enabledcapabilities)) { $attributes['noname'] = 1; } if (!in_array('Person.email.primary', $enabledcapabilities)) { $attributes['noemail'] = 1; } } else { if ($type->course == $COURSE->id) { $attributes = array('editable' => 1, 'courseTool' => 1, 'domain' => $type->tooldomain); } else { if ($id != 0) { $attributes = array('globalTool' => 1, 'domain' => $type->tooldomain); } else { $attributes = array(); } } } if (!$update && $id) { $config = lti_get_type_config($id); if (!empty($config['contentitem'])) { $attributes['data-contentitem'] = 1; $attributes['data-id'] = $id; } else { $noncontentitemtypes[] = $id; } } $tooltypes->addOption($type->name, $id, $attributes); } // Add button that launches the content-item selection dialogue. // Set contentitem URL. $contentitemurl = new moodle_url('/mod/lti/contentitem.php'); $contentbuttonattributes['data-contentitemurl'] = $contentitemurl->out(false); $mform->addElement('button', 'selectcontent', get_string('selectcontent', 'lti'), $contentbuttonattributes); if ($update) { $mform->disabledIf('selectcontent', 'typeid', 'neq', 0); } else { // Disable select content button if the selected tool doesn't support content item or it's set to Automatic. $allnoncontentitemtypes = $noncontentitemtypes; $allnoncontentitemtypes[] = '0'; // Add option value for "Automatic, based on launch URL". $mform->disabledIf('selectcontent', 'typeid', 'in', $allnoncontentitemtypes); } $mform->addElement('text', 'toolurl', get_string('launch_url', 'lti'), array('size' => '64')); $mform->setType('toolurl', PARAM_URL); $mform->addHelpButton('toolurl', 'launch_url', 'lti'); if ($update) { $mform->disabledIf('toolurl', 'typeid', 'neq', 0); } else { $mform->disabledIf('toolurl', 'typeid', 'in', $noncontentitemtypes); } $mform->addElement('text', 'securetoolurl', get_string('secure_launch_url', 'lti'), array('size' => '64')); $mform->setType('securetoolurl', PARAM_URL); $mform->setAdvanced('securetoolurl'); $mform->addHelpButton('securetoolurl', 'secure_launch_url', 'lti'); if ($update) { $mform->disabledIf('securetoolurl', 'typeid', 'neq', 0); } else { $mform->disabledIf('securetoolurl', 'typeid', 'in', $noncontentitemtypes); } $mform->addElement('hidden', 'urlmatchedtypeid', '', array('id' => 'id_urlmatchedtypeid')); $mform->setType('urlmatchedtypeid', PARAM_INT); $launchoptions = array(); $launchoptions[LTI_LAUNCH_CONTAINER_DEFAULT] = get_string('default', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_EMBED] = get_string('embed', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS] = get_string('embed_no_blocks', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW] = get_string('existing_window', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_WINDOW] = get_string('new_window', 'lti'); $mform->addElement('select', 'launchcontainer', get_string('launchinpopup', 'lti'), $launchoptions); $mform->setDefault('launchcontainer', LTI_LAUNCH_CONTAINER_DEFAULT); $mform->addHelpButton('launchcontainer', 'launchinpopup', 'lti'); $mform->setAdvanced('launchcontainer'); $mform->addElement('text', 'resourcekey', get_string('resourcekey', 'lti')); $mform->setType('resourcekey', PARAM_TEXT); $mform->setAdvanced('resourcekey'); $mform->addHelpButton('resourcekey', 'resourcekey', 'lti'); if ($update) { $mform->disabledIf('resourcekey', 'typeid', 'neq', 0); } else { $mform->disabledIf('resourcekey', 'typeid', 'in', $noncontentitemtypes); } $mform->setForceLtr('resourcekey'); $mform->addElement('passwordunmask', 'password', get_string('password', 'lti')); $mform->setType('password', PARAM_TEXT); $mform->setAdvanced('password'); $mform->addHelpButton('password', 'password', 'lti'); if ($update) { $mform->disabledIf('password', 'typeid', 'neq', 0); } else { $mform->disabledIf('password', 'typeid', 'in', $noncontentitemtypes); } $mform->addElement('textarea', 'instructorcustomparameters', get_string('custom', 'lti'), array('rows' => 4, 'cols' => 60)); $mform->setType('instructorcustomparameters', PARAM_TEXT); $mform->setAdvanced('instructorcustomparameters'); $mform->addHelpButton('instructorcustomparameters', 'custom', 'lti'); $mform->setForceLtr('instructorcustomparameters'); $mform->addElement('text', 'icon', get_string('icon_url', 'lti'), array('size' => '64')); $mform->setType('icon', PARAM_URL); $mform->setAdvanced('icon'); $mform->addHelpButton('icon', 'icon_url', 'lti'); if ($update) { $mform->disabledIf('icon', 'typeid', 'neq', 0); } else { $mform->disabledIf('icon', 'typeid', 'in', $noncontentitemtypes); } $mform->addElement('text', 'secureicon', get_string('secure_icon_url', 'lti'), array('size' => '64')); $mform->setType('secureicon', PARAM_URL); $mform->setAdvanced('secureicon'); $mform->addHelpButton('secureicon', 'secure_icon_url', 'lti'); if ($update) { $mform->disabledIf('secureicon', 'typeid', 'neq', 0); } else { $mform->disabledIf('secureicon', 'typeid', 'in', $noncontentitemtypes); } // Add privacy preferences fieldset where users choose whether to send their data. $mform->addElement('header', 'privacy', get_string('privacy', 'lti')); $mform->addElement('advcheckbox', 'instructorchoicesendname', ' ', ' ' . get_string('share_name', 'lti')); $mform->setDefault('instructorchoicesendname', '1'); $mform->addHelpButton('instructorchoicesendname', 'share_name', 'lti'); $mform->disabledIf('instructorchoicesendname', 'typeid', 'in', $toolproxy); $mform->addElement('advcheckbox', 'instructorchoicesendemailaddr', ' ', ' ' . get_string('share_email', 'lti')); $mform->setDefault('instructorchoicesendemailaddr', '1'); $mform->addHelpButton('instructorchoicesendemailaddr', 'share_email', 'lti'); $mform->disabledIf('instructorchoicesendemailaddr', 'typeid', 'in', $toolproxy); $mform->addElement('advcheckbox', 'instructorchoiceacceptgrades', ' ', ' ' . get_string('accept_grades', 'lti')); $mform->setDefault('instructorchoiceacceptgrades', '1'); $mform->addHelpButton('instructorchoiceacceptgrades', 'accept_grades', 'lti'); $mform->disabledIf('instructorchoiceacceptgrades', 'typeid', 'in', $toolproxy); // Add standard course module grading elements. $this->standard_grading_coursemodule_elements(); // Add standard elements, common to all modules. $this->standard_coursemodule_elements(); $mform->setAdvanced('cmidnumber'); // Add standard buttons, common to all modules. $this->add_action_buttons(); $editurl = new moodle_url('/mod/lti/instructor_edit_tool_type.php', array('sesskey' => sesskey(), 'course' => $COURSE->id)); $ajaxurl = new moodle_url('/mod/lti/ajax.php'); $jsinfo = (object) array('edit_icon_url' => (string) $OUTPUT->pix_url('t/edit'), 'add_icon_url' => (string) $OUTPUT->pix_url('t/add'), 'delete_icon_url' => (string) $OUTPUT->pix_url('t/delete'), 'green_check_icon_url' => (string) $OUTPUT->pix_url('i/valid'), 'warning_icon_url' => (string) $OUTPUT->pix_url('warning', 'lti'), 'instructor_tool_type_edit_url' => $editurl->out(false), 'ajax_url' => $ajaxurl->out(true), 'courseId' => $COURSE->id); $module = array('name' => 'mod_lti_edit', 'fullpath' => '/mod/lti/mod_form.js', 'requires' => array('base', 'io', 'querystring-stringify-simple', 'node', 'event', 'json-parse'), 'strings' => array(array('addtype', 'lti'), array('edittype', 'lti'), array('deletetype', 'lti'), array('delete_confirmation', 'lti'), array('cannot_edit', 'lti'), array('cannot_delete', 'lti'), array('global_tool_types', 'lti'), array('course_tool_types', 'lti'), array('using_tool_configuration', 'lti'), array('using_tool_cartridge', 'lti'), array('domain_mismatch', 'lti'), array('custom_config', 'lti'), array('tool_config_not_found', 'lti'), array('tooltypeadded', 'lti'), array('tooltypedeleted', 'lti'), array('tooltypenotdeleted', 'lti'), array('tooltypeupdated', 'lti'), array('forced_help', 'lti'))); if (!empty($typeid)) { $mform->setAdvanced('typeid'); $mform->setAdvanced('toolurl'); } $PAGE->requires->js_init_call('M.mod_lti.editor.init', array(json_encode($jsinfo)), true, $module); }
/** * @param stdClass $comment * @param stdClass $options * @throws comment_exception */ function mod_hsuforum_comment_message(stdClass $comment, stdClass $options) { global $DB; if ($options->commentarea != 'userposts_comments') { throw new comment_exception('invalidcommentarea'); } if (!($user = $DB->get_record('user', array('id' => $options->itemid)))) { throw new comment_exception('invalidcommentitemid'); } /** @var context $context */ $context = $options->context; if (!($cm = get_coursemodule_from_id('hsuforum', $context->instanceid))) { throw new comment_exception('invalidcontext'); } // Get all the users with the ability to rate. $recipients = get_users_by_capability($context, 'mod/hsuforum:rate'); // Add the item user if they are different from commenter. if ($comment->userid != $user->id and has_capability('mod/hsuforum:replypost', $context, $user)) { $recipients[$user->id] = $user; } // Sender is the author of the comment. $sender = $DB->get_record('user', array('id' => $comment->userid)); // Make sure that the commenter is not getting the message. unset($recipients[$comment->userid]); if (\core_component::get_plugin_directory('local', 'joulegrader') !== null) { // Joule Grader is installed and control panel enabled. $gareaid = component_callback('local_joulegrader', 'area_from_context', array($context, 'hsuforum')); $contexturl = new moodle_url('/local/joulegrader/view.php', array('courseid' => $cm->course, 'garea' => $gareaid, 'guser' => $user->id)); } else { $contexturl = $context->get_url(); } $params = array($comment, $recipients, $sender, $cm->name, $contexturl); component_callback('local_mrooms', 'comment_send_messages', $params); }
/** * Return aliases of this activity. LTI should have an alias for each configured tool type * This is so you can add an external tool types directly to the activity chooser * * @param stdClass $defaultitem default item that would be added to the activity chooser if this callback was not present. * It has properties: archetype, name, title, help, icon, link * @return array An array of aliases for this activity. Each element is an object with same list of properties as $defaultitem, * plus an additional property, helplink. * Properties title and link are required **/ function lti_get_shortcuts($defaultitem) { global $CFG, $COURSE; require_once $CFG->dirroot . '/mod/lti/locallib.php'; $types = lti_get_configured_types($COURSE->id, $defaultitem->link->param('sr')); $types[] = $defaultitem; // Add items defined in ltisource plugins. foreach (core_component::get_plugin_list('ltisource') as $pluginname => $dir) { if ($moretypes = component_callback("ltisource_{$pluginname}", 'get_types')) { // Callback 'get_types()' in 'ltisource' plugins is deprecated in 3.1 and will be removed in 3.5, TODO MDL-53697. debugging('Deprecated callback get_types() is found in ltisource_' . $pluginname . ', use get_shortcuts() instead', DEBUG_DEVELOPER); $grouptitle = get_string('modulenameplural', 'mod_lti'); foreach ($moretypes as $subtype) { // Instead of adding subitems combine the name of the group with the name of the subtype. $subtype->title = get_string('activitytypetitle', '', (object) ['activity' => $grouptitle, 'type' => $subtype->typestr]); // Re-implement the logic of get_module_metadata() in Moodle 3.0 and below for converting // subtypes into items in activity chooser. $subtype->type = str_replace('&', '&', $subtype->type); $subtype->name = preg_replace('/.*type=/', '', $subtype->type); $subtype->link = new moodle_url($defaultitem->link, array('type' => $subtype->name)); if (empty($subtype->help) && !empty($subtype->name) && get_string_manager()->string_exists('help' . $subtype->name, $pluginname)) { $subtype->help = get_string('help' . $subtype->name, $pluginname); } unset($subtype->typestr); $types[] = $subtype; } } // LTISOURCE plugins can also implement callback get_shortcuts() to add items to the activity chooser. // The return values are the same as of the 'mod' callbacks except that $defaultitem is only passed for reference and // should not be added to the return value. if ($moretypes = component_callback("ltisource_{$pluginname}", 'get_shortcuts', array($defaultitem))) { $types = array_merge($types, $moretypes); } } return $types; }
/** * Retrieve a list of ratings for a given item (forum post etc) * * @param string $contextlevel course, module, user... * @param int $instanceid the instance if for the context element * @param string $component the name of the component * @param string $ratingarea rating area * @param int $itemid the item id * @param int $scaleid the scale id * @param string $sort sql order (firstname, rating or timemodified) * @return array Result and possible warnings * @throws moodle_exception * @since Moodle 2.9 */ public static function get_item_ratings($contextlevel, $instanceid, $component, $ratingarea, $itemid, $scaleid, $sort) { global $USER, $PAGE; $warnings = array(); $arrayparams = array('contextlevel' => $contextlevel, 'instanceid' => $instanceid, 'component' => $component, 'ratingarea' => $ratingarea, 'itemid' => $itemid, 'scaleid' => $scaleid, 'sort' => $sort); // Validate and normalize parameters. $params = self::validate_parameters(self::get_item_ratings_parameters(), $arrayparams); $context = self::get_context_from_params($params); self::validate_context($context); // Minimal capability required. $callbackparams = array('contextid' => $context->id, 'component' => $component, 'ratingarea' => $ratingarea, 'itemid' => $itemid, 'scaleid' => $scaleid); if (!has_capability('moodle/rating:view', $context) || !component_callback($component, 'rating_can_see_item_ratings', array($callbackparams), true)) { throw new moodle_exception('noviewrate', 'rating'); } list($context, $course, $cm) = get_context_info_array($context->id); // Can we see all ratings? $canviewallratings = has_capability('moodle/rating:viewall', $context); // Create the Sql sort order string. switch ($params['sort']) { case 'firstname': $sqlsort = "u.firstname ASC"; break; case 'rating': $sqlsort = "r.rating ASC"; break; default: $sqlsort = "r.timemodified ASC"; } $ratingoptions = new stdClass(); $ratingoptions->context = $context; $ratingoptions->component = $params['component']; $ratingoptions->ratingarea = $params['ratingarea']; $ratingoptions->itemid = $params['itemid']; $ratingoptions->sort = $sqlsort; $rm = new rating_manager(); $ratings = $rm->get_all_ratings_for_item($ratingoptions); $scalemenu = make_grades_menu($params['scaleid']); // If the scale was changed after ratings were submitted some ratings may have a value above the current maximum. // We can't just do count($scalemenu) - 1 as custom scales start at index 1, not 0. $maxrating = max(array_keys($scalemenu)); $results = array(); foreach ($ratings as $rating) { if ($canviewallratings || $USER->id == $rating->userid) { if ($rating->rating > $maxrating) { $rating->rating = $maxrating; } // The rating object has all the required fields for generating the picture url. $userpicture = new user_picture($rating); $userpicture->size = 1; // Size f1. $profileimageurl = $userpicture->get_url($PAGE)->out(false); $result = array(); $result['id'] = $rating->id; $result['userid'] = $rating->userid; $result['userpictureurl'] = $profileimageurl; $result['userfullname'] = fullname($rating); $result['rating'] = $scalemenu[$rating->rating]; $result['timemodified'] = $rating->timemodified; $results[] = $result; } } return array('ratings' => $results, 'warnings' => $warnings); }
/** * Checks if the activity type requires subtypes. * * @return bool|null (null if the check is not possible) */ public function activity_has_subtypes() { if (!($modname = $this->get_activitytype())) { return null; } return component_callback('mod_' . $modname, 'get_types', array(), MOD_SUBTYPE_NO_CHILDREN) !== MOD_SUBTYPE_NO_CHILDREN; }
public function definition() { global $DB, $PAGE, $OUTPUT, $USER, $COURSE; if ($type = optional_param('type', false, PARAM_ALPHA)) { component_callback("ltisource_{$type}", 'add_instance_hook'); } $this->typeid = 0; $mform =& $this->_form; //------------------------------------------------------------------------------- // Adding the "general" fieldset, where all the common settings are shown $mform->addElement('header', 'general', get_string('general', 'form')); // Adding the standard "name" field $mform->addElement('text', 'name', get_string('basicltiname', 'lti'), array('size' => '64')); $mform->setType('name', PARAM_TEXT); $mform->addRule('name', null, 'required', null, 'client'); $mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); // Adding the optional "intro" and "introformat" pair of fields $this->add_intro_editor(false, get_string('basicltiintro', 'lti')); $mform->setAdvanced('introeditor'); // Display the label to the right of the checkbox so it looks better & matches rest of the form $coursedesc = $mform->getElement('showdescription'); if (!empty($coursedesc)) { $coursedesc->setText(' ' . $coursedesc->getLabel()); $coursedesc->setLabel(' '); } $mform->setAdvanced('showdescription'); $mform->addElement('checkbox', 'showtitlelaunch', ' ', ' ' . get_string('display_name', 'lti')); $mform->setAdvanced('showtitlelaunch'); $mform->setDefault('showtitlelaunch', true); $mform->addHelpButton('showtitlelaunch', 'display_name', 'lti'); $mform->addElement('checkbox', 'showdescriptionlaunch', ' ', ' ' . get_string('display_description', 'lti')); $mform->setAdvanced('showdescriptionlaunch'); $mform->addHelpButton('showdescriptionlaunch', 'display_description', 'lti'); // Tool settings $tooltypes = $mform->addElement('select', 'typeid', get_string('external_tool_type', 'lti'), array()); $mform->addHelpButton('typeid', 'external_tool_type', 'lti'); foreach (lti_get_types_for_add_instance() as $id => $type) { if ($type->course == $COURSE->id) { $attributes = array('editable' => 1, 'courseTool' => 1, 'domain' => $type->tooldomain); } else { if ($id != 0) { $attributes = array('globalTool' => 1, 'domain' => $type->tooldomain); } else { $attributes = array(); } } $tooltypes->addOption($type->name, $id, $attributes); } $mform->addElement('text', 'toolurl', get_string('launch_url', 'lti'), array('size' => '64')); $mform->setType('toolurl', PARAM_TEXT); $mform->addHelpButton('toolurl', 'launch_url', 'lti'); $mform->addElement('text', 'securetoolurl', get_string('secure_launch_url', 'lti'), array('size' => '64')); $mform->setType('securetoolurl', PARAM_TEXT); $mform->setAdvanced('securetoolurl'); $mform->addHelpButton('securetoolurl', 'secure_launch_url', 'lti'); $mform->addElement('hidden', 'urlmatchedtypeid', '', array('id' => 'id_urlmatchedtypeid')); $mform->setType('urlmatchedtypeid', PARAM_INT); $launchoptions = array(); $launchoptions[LTI_LAUNCH_CONTAINER_DEFAULT] = get_string('default', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_EMBED] = get_string('embed', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS] = get_string('embed_no_blocks', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW] = get_string('existing_window', 'lti'); $launchoptions[LTI_LAUNCH_CONTAINER_WINDOW] = get_string('new_window', 'lti'); $mform->addElement('select', 'launchcontainer', get_string('launchinpopup', 'lti'), $launchoptions); $mform->setDefault('launchcontainer', LTI_LAUNCH_CONTAINER_DEFAULT); $mform->addHelpButton('launchcontainer', 'launchinpopup', 'lti'); $mform->addElement('text', 'resourcekey', get_string('resourcekey', 'lti')); $mform->setType('resourcekey', PARAM_TEXT); $mform->setAdvanced('resourcekey'); $mform->addHelpButton('resourcekey', 'resourcekey', 'lti'); $mform->addElement('passwordunmask', 'password', get_string('password', 'lti')); $mform->setType('password', PARAM_TEXT); $mform->setAdvanced('password'); $mform->addHelpButton('password', 'password', 'lti'); $mform->addElement('textarea', 'instructorcustomparameters', get_string('custom', 'lti'), array('rows' => 4, 'cols' => 60)); $mform->setType('instructorcustomparameters', PARAM_TEXT); $mform->setAdvanced('instructorcustomparameters'); $mform->addHelpButton('instructorcustomparameters', 'custom', 'lti'); $mform->addElement('text', 'icon', get_string('icon_url', 'lti'), array('size' => '64')); $mform->setType('icon', PARAM_TEXT); $mform->setAdvanced('icon'); $mform->addHelpButton('icon', 'icon_url', 'lti'); $mform->addElement('text', 'secureicon', get_string('secure_icon_url', 'lti'), array('size' => '64')); $mform->setType('secureicon', PARAM_TEXT); $mform->setAdvanced('secureicon'); $mform->addHelpButton('secureicon', 'secure_icon_url', 'lti'); //------------------------------------------------------------------------------- // Add privacy preferences fieldset where users choose whether to send their data $mform->addElement('header', 'privacy', get_string('privacy', 'lti')); $mform->addElement('advcheckbox', 'instructorchoicesendname', ' ', ' ' . get_string('share_name', 'lti')); $mform->setDefault('instructorchoicesendname', '1'); $mform->addHelpButton('instructorchoicesendname', 'share_name', 'lti'); $mform->addElement('advcheckbox', 'instructorchoicesendemailaddr', ' ', ' ' . get_string('share_email', 'lti')); $mform->setDefault('instructorchoicesendemailaddr', '1'); $mform->addHelpButton('instructorchoicesendemailaddr', 'share_email', 'lti'); $mform->addElement('advcheckbox', 'instructorchoiceacceptgrades', ' ', ' ' . get_string('accept_grades', 'lti')); $mform->setDefault('instructorchoiceacceptgrades', '1'); $mform->addHelpButton('instructorchoiceacceptgrades', 'accept_grades', 'lti'); //$mform->addElement('checkbox', 'instructorchoiceallowroster', ' ', ' ' . get_string('share_roster', 'lti')); //$mform->setDefault('instructorchoiceallowroster', '1'); //$mform->addHelpButton('instructorchoiceallowroster', 'share_roster', 'lti'); //------------------------------------------------------------------------------- /** $debugoptions=array(); $debugoptions[0] = get_string('debuglaunchoff', 'lti'); $debugoptions[1] = get_string('debuglaunchon', 'lti'); $mform->addElement('select', 'debuglaunch', get_string('debuglaunch', 'lti'), $debugoptions); if (isset($this->typeconfig['debuglaunch'])) { if ($this->typeconfig['debuglaunch'] == 0) { $mform->setDefault('debuglaunch', '0'); } else if ($this->typeconfig['debuglaunch'] == 1) { $mform->setDefault('debuglaunch', '1'); } } */ // Add standard course module grading elements. $this->standard_grading_coursemodule_elements(); //------------------------------------------------------------------------------- // add standard elements, common to all modules $this->standard_coursemodule_elements(); $mform->setAdvanced('cmidnumber'); //------------------------------------------------------------------------------- // add standard buttons, common to all modules $this->add_action_buttons(); $editurl = new moodle_url('/mod/lti/instructor_edit_tool_type.php', array('sesskey' => sesskey(), 'course' => $COURSE->id)); $ajaxurl = new moodle_url('/mod/lti/ajax.php'); $jsinfo = (object) array('edit_icon_url' => (string) $OUTPUT->pix_url('t/edit'), 'add_icon_url' => (string) $OUTPUT->pix_url('t/add'), 'delete_icon_url' => (string) $OUTPUT->pix_url('t/delete'), 'green_check_icon_url' => (string) $OUTPUT->pix_url('i/valid'), 'warning_icon_url' => (string) $OUTPUT->pix_url('warning', 'lti'), 'instructor_tool_type_edit_url' => $editurl->out(false), 'ajax_url' => $ajaxurl->out(true), 'courseId' => $COURSE->id); $module = array('name' => 'mod_lti_edit', 'fullpath' => '/mod/lti/mod_form.js', 'requires' => array('base', 'io', 'querystring-stringify-simple', 'node', 'event', 'json-parse'), 'strings' => array(array('addtype', 'lti'), array('edittype', 'lti'), array('deletetype', 'lti'), array('delete_confirmation', 'lti'), array('cannot_edit', 'lti'), array('cannot_delete', 'lti'), array('global_tool_types', 'lti'), array('course_tool_types', 'lti'), array('using_tool_configuration', 'lti'), array('domain_mismatch', 'lti'), array('custom_config', 'lti'), array('tool_config_not_found', 'lti'), array('forced_help', 'lti'))); $PAGE->requires->js_init_call('M.mod_lti.editor.init', array(json_encode($jsinfo)), true, $module); }
/** * Test update_inplace_editable() */ public function test_update_inplace_editable() { global $CFG, $DB, $PAGE; require_once $CFG->dirroot . '/lib/external/externallib.php'; $this->resetAfterTest(true); $tag = $this->getDataGenerator()->create_tag(); $this->setUser($this->getDataGenerator()->create_user()); // Call service for core_tag component without necessary permissions. try { core_external::update_inplace_editable('core_tag', 'tagname', $tag->id, 'new tag name'); $this->fail('Exception expected'); } catch (moodle_exception $e) { $this->assertEquals('Sorry, but you do not currently have permissions to do that (Manage all tags)', $e->getMessage()); } // Change to admin user and make sure that tag name can be updated using web service update_inplace_editable(). $this->setAdminUser(); $res = core_external::update_inplace_editable('core_tag', 'tagname', $tag->id, 'New tag name'); $res = external_api::clean_returnvalue(core_external::update_inplace_editable_returns(), $res); $this->assertEquals('New tag name', $res['value']); $this->assertEquals('New tag name', $DB->get_field('tag', 'rawname', array('id' => $tag->id))); // Call callback core_tag_inplace_editable() directly. $tmpl = component_callback('core_tag', 'inplace_editable', array('tagname', $tag->id, 'Rename me again')); $this->assertInstanceOf('core\\output\\inplace_editable', $tmpl); $res = $tmpl->export_for_template($PAGE->get_renderer('core')); $this->assertEquals('Rename me again', $res['value']); $this->assertEquals('Rename me again', $DB->get_field('tag', 'rawname', array('id' => $tag->id))); }
/** * Is the gradebook accessible - i.e. are there any reports accessible to this user * @return bool */ public static function gradebook_accessible($context) { global $COURSE; // Ask if user has not capabilities and if course is set to not to show the grades to students. if (!has_capability('gradereport/grader:view', $context) && $COURSE->showgrades == 0) { return false; } // Find all enabled reports. $reports = core_component::get_plugin_list('gradereport'); foreach (array_keys($reports) as $report) { if (!component_callback('gradereport_' . $report, 'is_enabled', array(), true)) { unset($reports[$report]); } } // Reduce reports list down to just those accessible to user. foreach ($reports as $plugin => $plugindir) { // Remove ones we can't see. if (!has_capability('gradereport/' . $plugin . ':view', $context)) { unset($reports[$plugin]); } } return !empty($reports); }
/** * Get a HTML fragment for inserting into something. Initial use is for inserting mforms into * a page using AJAX. * This web service is designed to be called only via AJAX and not directly. * Callbacks that are called by this web service are responsible for doing the appropriate security checks * to access the information returned. This only does minimal validation on the context. * * @param string $component Name of the component. * @param string $callback Function callback name. * @param int $contextid Context ID this fragment is in. * @param array $args optional arguments for the callback. * @return array HTML and JavaScript fragments for insertion into stuff. * @since Moodle 3.1 */ public static function get_fragment($component, $callback, $contextid, $args = null) { global $OUTPUT, $PAGE; $params = self::validate_parameters(self::get_fragment_parameters(), array('component' => $component, 'callback' => $callback, 'contextid' => $contextid, 'args' => $args)); // Reformat arguments into something less unwieldy. $arguments = array(); foreach ($params['args'] as $paramargument) { $arguments[$paramargument['name']] = $paramargument['value']; } $context = context::instance_by_id($contextid); self::validate_context($context); // Hack alert: Forcing bootstrap_renderer to initiate moodle page. $OUTPUT->header(); // Overwriting page_requirements_manager with the fragment one so only JS included from // this point is returned to the user. $PAGE->start_collecting_javascript_requirements(); $data = component_callback($params['component'], 'output_fragment_' . $params['callback'], $arguments); $jsfooter = $PAGE->requires->get_end_code(); $output = array('html' => $data, 'javascript' => $jsfooter); return $output; }
/** * Is the gradebook accessible - i.e. are there any reports accessible to this user * @return bool */ public static function gradebook_accessible($context) { // Find all enabled reports. $reports = core_component::get_plugin_list('gradereport'); foreach (array_keys($reports) as $report) { if (!component_callback('gradereport_' . $report, 'is_enabled', array(), true)) { unset($reports[$report]); } } // Reduce reports list down to just those accessible to user. foreach ($reports as $plugin => $plugindir) { // Remove ones we can't see. if (!has_capability('gradereport/' . $plugin . ':view', $context)) { unset($reports[$plugin]); } } return !empty($reports); }
/** * Test callback updating section name */ public function test_inplace_editable() { global $CFG, $DB, $PAGE; $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); $course = $this->getDataGenerator()->create_course(array('numsections' => 5, 'format' => 'weeks'), array('createsections' => true)); $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); $this->getDataGenerator()->enrol_user($user->id, $course->id, $teacherrole->id); $this->setUser($user); $section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2)); // Call callback format_weeks_inplace_editable() directly. $tmpl = component_callback('format_weeks', 'inplace_editable', array('sectionname', $section->id, 'Rename me again')); $this->assertInstanceOf('core\\output\\inplace_editable', $tmpl); $res = $tmpl->export_for_template($PAGE->get_renderer('core')); $this->assertEquals('Rename me again', $res['value']); $this->assertEquals('Rename me again', $DB->get_field('course_sections', 'name', array('id' => $section->id))); // Try updating using callback from mismatching course format. try { $tmpl = component_callback('format_topics', 'inplace_editable', array('sectionname', $section->id, 'New name')); $this->fail('Exception expected'); } catch (moodle_exception $e) { $this->assertEquals(1, preg_match('/^Can not find data record in database/', $e->getMessage())); } }
/** * Builds a standard LTI Content-Item selection request. * * @param int $id The tool type ID. * @param stdClass $course The course object. * @param moodle_url $returnurl The return URL in the tool consumer (TC) that the tool provider (TP) * will use to return the Content-Item message. * @param string $title The tool's title, if available. * @param string $text The text to display to represent the content item. This value may be a long description of the content item. * @param array $mediatypes Array of MIME types types supported by the TC. If empty, the TC will support ltilink by default. * @param array $presentationtargets Array of ways in which the selected content item(s) can be requested to be opened * (via the presentationDocumentTarget element for a returned content item). * If empty, "frame", "iframe", and "window" will be supported by default. * @param bool $autocreate Indicates whether any content items returned by the TP would be automatically persisted without * @param bool $multiple Indicates whether the user should be permitted to select more than one item. False by default. * any option for the user to cancel the operation. False by default. * @param bool $unsigned Indicates whether the TC is willing to accept an unsigned return message, or not. * A signed message should always be required when the content item is being created automatically in the * TC without further interaction from the user. False by default. * @param bool $canconfirm Flag for can_confirm parameter. False by default. * @param bool $copyadvice Indicates whether the TC is able and willing to make a local copy of a content item. False by default. * @return stdClass The object containing the signed request parameters and the URL to the TP's Content-Item selection interface. * @throws moodle_exception When the LTI tool type does not exist.` * @throws coding_exception For invalid media type and presentation target parameters. */ function lti_build_content_item_selection_request($id, $course, moodle_url $returnurl, $title = '', $text = '', $mediatypes = [], $presentationtargets = [], $autocreate = false, $multiple = false, $unsigned = false, $canconfirm = false, $copyadvice = false) { $tool = lti_get_type($id); // Validate parameters. if (!$tool) { throw new moodle_exception('errortooltypenotfound', 'mod_lti'); } if (!is_array($mediatypes)) { throw new coding_exception('The list of accepted media types should be in an array'); } if (!is_array($presentationtargets)) { throw new coding_exception('The list of accepted presentation targets should be in an array'); } // Check title. If empty, use the tool's name. if (empty($title)) { $title = $tool->name; } $typeconfig = lti_get_type_config($id); $key = ''; $secret = ''; $islti2 = false; if (isset($tool->toolproxyid)) { $islti2 = true; $toolproxy = lti_get_tool_proxy($tool->toolproxyid); $key = $toolproxy->guid; $secret = $toolproxy->secret; } else { $toolproxy = null; if (!empty($typeconfig['resourcekey'])) { $key = $typeconfig['resourcekey']; } if (!empty($typeconfig['password'])) { $secret = $typeconfig['password']; } } $tool->enabledcapability = ''; if (!empty($typeconfig['enabledcapability_ContentItemSelectionRequest'])) { $tool->enabledcapability = $typeconfig['enabledcapability_ContentItemSelectionRequest']; } $tool->parameter = ''; if (!empty($typeconfig['parameter_ContentItemSelectionRequest'])) { $tool->parameter = $typeconfig['parameter_ContentItemSelectionRequest']; } // Set the tool URL. if (!empty($typeconfig['toolurl_ContentItemSelectionRequest'])) { $toolurl = new moodle_url($typeconfig['toolurl_ContentItemSelectionRequest']); } else { $toolurl = new moodle_url($typeconfig['toolurl']); } // Check if SSL is forced. if (!empty($typeconfig['forcessl'])) { // Make sure the tool URL is set to https. if (strtolower($toolurl->get_scheme()) === 'http') { $toolurl->set_scheme('https'); } // Make sure the return URL is set to https. if (strtolower($returnurl->get_scheme()) === 'http') { $returnurl->set_scheme('https'); } } $toolurlout = $toolurl->out(false); // Get base request parameters. $instance = new stdClass(); $instance->course = $course->id; $requestparams = lti_build_request($instance, $typeconfig, $course, $id, $islti2); // Get LTI2-specific request parameters and merge to the request parameters if applicable. if ($islti2) { $lti2params = lti_build_request_lti2($tool, $requestparams); $requestparams = array_merge($requestparams, $lti2params); } // Get standard request parameters and merge to the request parameters. $orgid = !empty($typeconfig['organizationid']) ? $typeconfig['organizationid'] : ''; $standardparams = lti_build_standard_request(null, $orgid, $islti2, 'ContentItemSelectionRequest'); $requestparams = array_merge($requestparams, $standardparams); // Get custom request parameters and merge to the request parameters. $customstr = ''; if (!empty($typeconfig['customparameters'])) { $customstr = $typeconfig['customparameters']; } $customparams = lti_build_custom_parameters($toolproxy, $tool, $instance, $requestparams, $customstr, '', $islti2); $requestparams = array_merge($requestparams, $customparams); // Allow request params to be updated by sub-plugins. $plugins = core_component::get_plugin_list('ltisource'); foreach (array_keys($plugins) as $plugin) { $pluginparams = component_callback('ltisource_' . $plugin, 'before_launch', [$instance, $toolurlout, $requestparams], []); if (!empty($pluginparams) && is_array($pluginparams)) { $requestparams = array_merge($requestparams, $pluginparams); } } // Media types. Set to ltilink by default if empty. if (empty($mediatypes)) { $mediatypes = ['application/vnd.ims.lti.v1.ltilink']; } $requestparams['accept_media_types'] = implode(',', $mediatypes); // Presentation targets. Supports frame, iframe, window by default if empty. if (empty($presentationtargets)) { $presentationtargets = ['frame', 'iframe', 'window']; } $requestparams['accept_presentation_document_targets'] = implode(',', $presentationtargets); // Other request parameters. $requestparams['accept_copy_advice'] = $copyadvice === true ? 'true' : 'false'; $requestparams['accept_multiple'] = $multiple === true ? 'true' : 'false'; $requestparams['accept_unsigned'] = $unsigned === true ? 'true' : 'false'; $requestparams['auto_create'] = $autocreate === true ? 'true' : 'false'; $requestparams['can_confirm'] = $canconfirm === true ? 'true' : 'false'; $requestparams['content_item_return_url'] = $returnurl->out(false); $requestparams['title'] = $title; $requestparams['text'] = $text; $signedparams = lti_sign_parameters($requestparams, $toolurlout, 'POST', $key, $secret); $toolurlparams = $toolurl->params(); // Strip querystring params in endpoint url from $signedparams to avoid duplication. if (!empty($toolurlparams) && !empty($signedparams)) { foreach (array_keys($toolurlparams) as $paramname) { if (isset($signedparams[$paramname])) { unset($signedparams[$paramname]); } } } // Check for params that should not be passed. Unset if they are set. $unwantedparams = ['resource_link_id', 'resource_link_title', 'resource_link_description', 'launch_presentation_return_url', 'lis_result_sourcedid']; foreach ($unwantedparams as $param) { if (isset($signedparams[$param])) { unset($signedparams[$param]); } } // Prepare result object. $result = new stdClass(); $result->params = $signedparams; $result->url = $toolurlout; return $result; }
/** * Returns list of recent activity within modules * * For each used module type executes callback MODULE_print_recent_activity() * * @return array array of pairs moduletype => content */ protected function get_modules_recent_activity() { $context = context_course::instance($this->page->course->id); $viewfullnames = has_capability('moodle/site:viewfullnames', $context); $hascontent = false; $modinfo = get_fast_modinfo($this->page->course); $usedmodules = $modinfo->get_used_module_names(); $recentactivity = array(); foreach ($usedmodules as $modname => $modfullname) { // Each module gets it's own logs and prints them ob_start(); $hascontent = component_callback('mod_' . $modname, 'print_recent_activity', array($this->page->course, $viewfullnames, $this->get_timestart()), false); if ($hascontent) { $recentactivity[$modname] = ob_get_contents(); } ob_end_clean(); } return $recentactivity; }
/** * Update the module info. * This function doesn't check the user capabilities. It updates the course module and the module instance. * Then execute common action to create/update module process (trigger event, rebuild cache, save plagiarism settings...). * * @param object $cm course module * @param object $moduleinfo module info * @param object $course course of the module * @param object $mform - the mform is required by some specific module in the function MODULE_update_instance(). This is due to a hack in this function. * @return array list of course module and module info. */ function update_moduleinfo($cm, $moduleinfo, $course, $mform = null) { global $DB, $CFG; $data = new stdClass(); if ($mform) { $data = $mform->get_data(); } // Attempt to include module library before we make any changes to DB. include_modulelib($moduleinfo->modulename); $moduleinfo->course = $course->id; $moduleinfo = set_moduleinfo_defaults($moduleinfo); if (!empty($course->groupmodeforce) or !isset($moduleinfo->groupmode)) { $moduleinfo->groupmode = $cm->groupmode; // Keep original. } // Update course module first. $cm->groupmode = $moduleinfo->groupmode; if (isset($moduleinfo->groupingid)) { $cm->groupingid = $moduleinfo->groupingid; } $completion = new completion_info($course); if ($completion->is_enabled()) { // Completion settings that would affect users who have already completed // the activity may be locked; if so, these should not be updated. if (!empty($moduleinfo->completionunlocked)) { $cm->completion = $moduleinfo->completion; $cm->completiongradeitemnumber = $moduleinfo->completiongradeitemnumber; $cm->completionview = $moduleinfo->completionview; } // The expected date does not affect users who have completed the activity, // so it is safe to update it regardless of the lock status. $cm->completionexpected = $moduleinfo->completionexpected; } if (!empty($CFG->enableavailability)) { // This code is used both when submitting the form, which uses a long // name to avoid clashes, and by unit test code which uses the real // name in the table. if (property_exists($moduleinfo, 'availabilityconditionsjson')) { if ($moduleinfo->availabilityconditionsjson !== '') { $cm->availability = $moduleinfo->availabilityconditionsjson; } else { $cm->availability = null; } } else { if (property_exists($moduleinfo, 'availability')) { $cm->availability = $moduleinfo->availability; } } // If there is any availability data, verify it. if ($cm->availability) { $tree = new \core_availability\tree(json_decode($cm->availability)); // Save time and database space by setting null if the only data // is an empty tree. if ($tree->is_empty()) { $cm->availability = null; } } } if (isset($moduleinfo->showdescription)) { $cm->showdescription = $moduleinfo->showdescription; } else { $cm->showdescription = 0; } $DB->update_record('course_modules', $cm); $modcontext = context_module::instance($moduleinfo->coursemodule); // Update embedded links and save files. if (plugin_supports('mod', $moduleinfo->modulename, FEATURE_MOD_INTRO, true)) { $moduleinfo->intro = file_save_draft_area_files($moduleinfo->introeditor['itemid'], $modcontext->id, 'mod_' . $moduleinfo->modulename, 'intro', 0, array('subdirs' => true), $moduleinfo->introeditor['text']); $moduleinfo->introformat = $moduleinfo->introeditor['format']; unset($moduleinfo->introeditor); } // Get the a copy of the grade_item before it is modified incase we need to scale the grades. $oldgradeitem = null; $newgradeitem = null; if (!empty($data->grade_rescalegrades) && $data->grade_rescalegrades == 'yes') { // Fetch the grade item before it is updated. $oldgradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $moduleinfo->modulename, 'iteminstance' => $moduleinfo->instance, 'itemnumber' => 0, 'courseid' => $moduleinfo->course)); } $updateinstancefunction = $moduleinfo->modulename . "_update_instance"; if (!$updateinstancefunction($moduleinfo, $mform)) { print_error('cannotupdatemod', '', course_get_url($course, $cm->section), $moduleinfo->modulename); } // This needs to happen AFTER the grademin/grademax have already been updated. if (!empty($data->grade_rescalegrades) && $data->grade_rescalegrades == 'yes') { // Get the grade_item after the update call the activity to scale the grades. $newgradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $moduleinfo->modulename, 'iteminstance' => $moduleinfo->instance, 'itemnumber' => 0, 'courseid' => $moduleinfo->course)); if ($newgradeitem && $oldgradeitem->gradetype == GRADE_TYPE_VALUE && $newgradeitem->gradetype == GRADE_TYPE_VALUE) { $params = array($course, $cm, $oldgradeitem->grademin, $oldgradeitem->grademax, $newgradeitem->grademin, $newgradeitem->grademax); if (!component_callback('mod_' . $moduleinfo->modulename, 'rescale_activity_grades', $params)) { print_error('cannotreprocessgrades', '', course_get_url($course, $cm->section), $moduleinfo->modulename); } } } // Make sure visibility is set correctly (in particular in calendar). if (has_capability('moodle/course:activityvisibility', $modcontext)) { set_coursemodule_visible($moduleinfo->coursemodule, $moduleinfo->visible); } if (isset($moduleinfo->cmidnumber)) { // Label. // Set cm idnumber - uniqueness is already verified by form validation. set_coursemodule_idnumber($moduleinfo->coursemodule, $moduleinfo->cmidnumber); } // Update module tags. if (core_tag_tag::is_enabled('core', 'course_modules') && isset($moduleinfo->tags)) { core_tag_tag::set_item_tags('core', 'course_modules', $moduleinfo->coursemodule, $modcontext, $moduleinfo->tags); } // Now that module is fully updated, also update completion data if required. // (this will wipe all user completion data and recalculate it) if ($completion->is_enabled() && !empty($moduleinfo->completionunlocked)) { $completion->reset_all_state($cm); } $cm->name = $moduleinfo->name; \core\event\course_module_updated::create_from_cm($cm, $modcontext)->trigger(); $moduleinfo = edit_module_post_actions($moduleinfo, $course); return array($cm, $moduleinfo); }
/** * Use this editor for given element. * * @param string $elementid * @param array $options * @param null $fpoptions */ public function use_editor($elementid, array $options = null, $fpoptions = null) { global $PAGE; $configstr = get_config('editor_atto', 'toolbar'); $grouplines = explode("\n", $configstr); $groups = array(); foreach ($grouplines as $groupline) { $line = explode('=', $groupline); if (count($line) > 1) { $group = trim(array_shift($line)); $plugins = array_map('trim', explode(',', array_shift($line))); $groups[$group] = $plugins; } } $modules = array('moodle-editor_atto-editor'); $options['context'] = empty($options['context']) ? context_system::instance() : $options['context']; $jsplugins = array(); foreach ($groups as $group => $plugins) { $groupplugins = array(); foreach ($plugins as $plugin) { // Do not die on missing plugin. if (!core_component::get_component_directory('atto_' . $plugin)) { continue; } $jsplugin = array(); $jsplugin['name'] = $plugin; $jsplugin['params'] = array(); $modules[] = 'moodle-atto_' . $plugin . '-button'; component_callback('atto_' . $plugin, 'strings_for_js'); $extra = component_callback('atto_' . $plugin, 'params_for_js', array($elementid, $options, $fpoptions)); if ($extra) { $jsplugin = array_merge($jsplugin, $extra); } // We always need the plugin name. $PAGE->requires->string_for_js('pluginname', 'atto_' . $plugin); $groupplugins[] = $jsplugin; } $jsplugins[] = array('group' => $group, 'plugins' => $groupplugins); } $PAGE->requires->strings_for_js(array('editor_command_keycode', 'editor_control_keycode', 'plugin_title_shortcut', 'textrecovered', 'autosavefailed', 'autosavesucceeded', 'errortextrecovery'), 'editor_atto'); $PAGE->requires->strings_for_js(array('warning', 'info'), 'moodle'); $PAGE->requires->yui_module($modules, 'Y.M.editor_atto.Editor.init', array($this->get_init_params($elementid, $options, $fpoptions, $jsplugins))); }
/** * Update any component's editable value assuming that component implements necessary callback * * @since Moodle 3.1 * @param string $component * @param string $itemtype * @param string $itemid * @param string $value */ public static function update_inplace_editable($component, $itemtype, $itemid, $value) { global $PAGE; // Validate and normalize parameters. $params = self::validate_parameters(self::update_inplace_editable_parameters(), array('component' => $component, 'itemtype' => $itemtype, 'itemid' => $itemid, 'value' => $value)); if (!($functionname = component_callback_exists($component, 'inplace_editable'))) { throw new \moodle_exception('inplaceeditableerror'); } $tmpl = component_callback($params['component'], 'inplace_editable', array($params['itemtype'], $params['itemid'], $params['value'])); if (!$tmpl || !$tmpl instanceof \core\output\inplace_editable) { throw new \moodle_exception('inplaceeditableerror'); } $PAGE->set_context(null); // To prevent warning if context was not set in the callback. return $tmpl->export_for_template($PAGE->get_renderer('core')); }
/** * Called by pluginfile.php to serve files related to the 'question' core * component and for files belonging to qtypes. * * For files that relate to questions in a question_attempt, then we delegate to * a function in the component that owns the attempt (for example in the quiz, * or in core question preview) to get necessary inforation. * * (Note that, at the moment, all question file areas relate to questions in * attempts, so the If at the start of the last paragraph is always true.) * * Does not return, either calls send_file_not_found(); or serves the file. * * @package core_question * @category files * @param stdClass $course course settings object * @param stdClass $context context object * @param string $component the name of the component we are serving files for. * @param string $filearea the name of the file area. * @param array $args the remaining bits of the file path. * @param bool $forcedownload whether the user must be forced to download the file. * @param array $options additional options affecting the file serving */ function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload, array $options = array()) { global $DB, $CFG; // Special case, sending a question bank export. if ($filearea === 'export') { list($context, $course, $cm) = get_context_info_array($context->id); require_login($course, false, $cm); require_once $CFG->dirroot . '/question/editlib.php'; $contexts = new question_edit_contexts($context); // check export capability $contexts->require_one_edit_tab_cap('export'); $category_id = (int) array_shift($args); $format = array_shift($args); $cattofile = array_shift($args); $contexttofile = array_shift($args); $filename = array_shift($args); // load parent class for import/export require_once $CFG->dirroot . '/question/format.php'; require_once $CFG->dirroot . '/question/editlib.php'; require_once $CFG->dirroot . '/question/format/' . $format . '/format.php'; $classname = 'qformat_' . $format; if (!class_exists($classname)) { send_file_not_found(); } $qformat = new $classname(); if (!($category = $DB->get_record('question_categories', array('id' => $category_id)))) { send_file_not_found(); } $qformat->setCategory($category); $qformat->setContexts($contexts->having_one_edit_tab_cap('export')); $qformat->setCourse($course); if ($cattofile == 'withcategories') { $qformat->setCattofile(true); } else { $qformat->setCattofile(false); } if ($contexttofile == 'withcontexts') { $qformat->setContexttofile(true); } else { $qformat->setContexttofile(false); } if (!$qformat->exportpreprocess()) { send_file_not_found(); print_error('exporterror', 'question', $thispageurl->out()); } // export data to moodle file pool if (!($content = $qformat->exportprocess(true))) { send_file_not_found(); } send_file($content, $filename, 0, 0, true, true, $qformat->mime_type()); } // Normal case, a file belonging to a question. $qubaidorpreview = array_shift($args); // Two sub-cases: 1. A question being previewed outside an attempt/usage. if ($qubaidorpreview === 'preview') { $previewcontextid = (int) array_shift($args); $previewcomponent = array_shift($args); $questionid = (int) array_shift($args); $previewcontext = context_helper::instance_by_id($previewcontextid); $result = component_callback($previewcomponent, 'question_preview_pluginfile', array($previewcontext, $questionid, $context, $component, $filearea, $args, $forcedownload, $options), 'newcallbackmissing'); if ($result === 'newcallbackmissing' && ($filearea = 'questiontext')) { // Fall back to the legacy callback for backwards compatibility. debugging("Component {$previewcomponent} does not define the expected " . "{$previewcomponent}_question_preview_pluginfile callback. Falling back to the deprecated " . "{$previewcomponent}_questiontext_preview_pluginfile callback.", DEBUG_DEVELOPER); component_callback($previewcomponent, 'questiontext_preview_pluginfile', array($previewcontext, $questionid, $args, $forcedownload, $options)); } send_file_not_found(); } // 2. A question being attempted in the normal way. $qubaid = (int) $qubaidorpreview; $slot = (int) array_shift($args); $module = $DB->get_field('question_usages', 'component', array('id' => $qubaid)); if ($module === 'core_question_preview') { require_once $CFG->dirroot . '/question/previewlib.php'; return question_preview_question_pluginfile($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload, $options); } else { $dir = core_component::get_component_directory($module); if (!file_exists("{$dir}/lib.php")) { send_file_not_found(); } include_once "{$dir}/lib.php"; $filefunction = $module . '_question_pluginfile'; if (function_exists($filefunction)) { $filefunction($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload, $options); } // Okay, we're here so lets check for function without 'mod_'. if (strpos($module, 'mod_') === 0) { $filefunctionold = substr($module, 4) . '_question_pluginfile'; if (function_exists($filefunctionold)) { $filefunctionold($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload, $options); } } send_file_not_found(); } }
/** * Return the launch data required for opening the external tool. * * @param stdClass $instance the external tool activity settings * @return array the endpoint URL and parameters (including the signature) * @since Moodle 3.0 */ function lti_get_launch_data($instance) { global $PAGE, $CFG; if (empty($instance->typeid)) { $tool = lti_get_tool_by_url_match($instance->toolurl, $instance->course); if ($tool) { $typeid = $tool->id; } else { $typeid = null; } } else { $typeid = $instance->typeid; $tool = lti_get_type($typeid); } if ($typeid) { $typeconfig = lti_get_type_config($typeid); } else { // There is no admin configuration for this tool. Use configuration in the lti instance record plus some defaults. $typeconfig = (array) $instance; $typeconfig['sendname'] = $instance->instructorchoicesendname; $typeconfig['sendemailaddr'] = $instance->instructorchoicesendemailaddr; $typeconfig['customparameters'] = $instance->instructorcustomparameters; $typeconfig['acceptgrades'] = $instance->instructorchoiceacceptgrades; $typeconfig['allowroster'] = $instance->instructorchoiceallowroster; $typeconfig['forcessl'] = '0'; } // Default the organizationid if not specified. if (empty($typeconfig['organizationid'])) { $urlparts = parse_url($CFG->wwwroot); $typeconfig['organizationid'] = $urlparts['host']; } if (isset($tool->toolproxyid)) { $toolproxy = lti_get_tool_proxy($tool->toolproxyid); $key = $toolproxy->guid; $secret = $toolproxy->secret; } else { $toolproxy = null; if (!empty($instance->resourcekey)) { $key = $instance->resourcekey; } else { if (!empty($typeconfig['resourcekey'])) { $key = $typeconfig['resourcekey']; } else { $key = ''; } } if (!empty($instance->password)) { $secret = $instance->password; } else { if (!empty($typeconfig['password'])) { $secret = $typeconfig['password']; } else { $secret = ''; } } } $endpoint = !empty($instance->toolurl) ? $instance->toolurl : $typeconfig['toolurl']; $endpoint = trim($endpoint); // If the current request is using SSL and a secure tool URL is specified, use it. if (lti_request_is_using_ssl() && !empty($instance->securetoolurl)) { $endpoint = trim($instance->securetoolurl); } // If SSL is forced, use the secure tool url if specified. Otherwise, make sure https is on the normal launch URL. if (isset($typeconfig['forcessl']) && $typeconfig['forcessl'] == '1') { if (!empty($instance->securetoolurl)) { $endpoint = trim($instance->securetoolurl); } $endpoint = lti_ensure_url_is_https($endpoint); } else { if (!strstr($endpoint, '://')) { $endpoint = 'http://' . $endpoint; } } $orgid = $typeconfig['organizationid']; $course = $PAGE->course; $islti2 = isset($tool->toolproxyid); $allparams = lti_build_request($instance, $typeconfig, $course, $typeid, $islti2); if ($islti2) { $requestparams = lti_build_request_lti2($tool, $allparams); } else { $requestparams = $allparams; } $requestparams = array_merge($requestparams, lti_build_standard_request($instance, $orgid, $islti2)); $customstr = ''; if (isset($typeconfig['customparameters'])) { $customstr = $typeconfig['customparameters']; } $requestparams = array_merge($requestparams, lti_build_custom_parameters($toolproxy, $tool, $instance, $allparams, $customstr, $instance->instructorcustomparameters, $islti2)); $launchcontainer = lti_get_launch_container($instance, $typeconfig); $returnurlparams = array('course' => $course->id, 'launch_container' => $launchcontainer, 'instanceid' => $instance->id, 'sesskey' => sesskey()); // Add the return URL. We send the launch container along to help us avoid frames-within-frames when the user returns. $url = new \moodle_url('/mod/lti/return.php', $returnurlparams); $returnurl = $url->out(false); if (isset($typeconfig['forcessl']) && $typeconfig['forcessl'] == '1') { $returnurl = lti_ensure_url_is_https($returnurl); } $target = ''; switch ($launchcontainer) { case LTI_LAUNCH_CONTAINER_EMBED: case LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS: $target = 'iframe'; break; case LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW: $target = 'frame'; break; case LTI_LAUNCH_CONTAINER_WINDOW: $target = 'window'; break; } if (!empty($target)) { $requestparams['launch_presentation_document_target'] = $target; } $requestparams['launch_presentation_return_url'] = $returnurl; // Allow request params to be updated by sub-plugins. $plugins = core_component::get_plugin_list('ltisource'); foreach (array_keys($plugins) as $plugin) { $pluginparams = component_callback('ltisource_' . $plugin, 'before_launch', array($instance, $endpoint, $requestparams), array()); if (!empty($pluginparams) && is_array($pluginparams)) { $requestparams = array_merge($requestparams, $pluginparams); } } if (!empty($key) && !empty($secret)) { $parms = lti_sign_parameters($requestparams, $endpoint, "POST", $key, $secret); $endpointurl = new \moodle_url($endpoint); $endpointparams = $endpointurl->params(); // Strip querystring params in endpoint url from $parms to avoid duplication. if (!empty($endpointparams) && !empty($parms)) { foreach (array_keys($endpointparams) as $paramname) { if (isset($parms[$paramname])) { unset($parms[$paramname]); } } } } else { // If no key and secret, do the launch unsigned. $returnurlparams['unsigned'] = '1'; $parms = $requestparams; } return array($endpoint, $parms); }
/** * Invoke plugin's callback functions * * @param string $type plugin type e.g. 'mod' * @param string $name plugin name * @param string $feature feature name * @param string $action feature's action * @param array $params parameters of callback function, should be an array * @param mixed $default default value if callback function hasn't been defined, or if it retursn null. * @return mixed * * @todo Decide about to deprecate and drop plugin_callback() - MDL-30743 */ function plugin_callback($type, $name, $feature, $action, $params = null, $default = null) { return component_callback($type . '_' . $name, $feature . '_' . $action, (array) $params, $default); }
/** * Called by pluginfile.php to serve files related to the 'question' core * component and for files belonging to qtypes. * * For files that relate to questions in a question_attempt, then we delegate to * a function in the component that owns the attempt (for example in the quiz, * or in core question preview) to get necessary inforation. * * (Note that, at the moment, all question file areas relate to questions in * attempts, so the If at the start of the last paragraph is always true.) * * Does not return, either calls send_file_not_found(); or serves the file. * * @package core_question * @category files * @param stdClass $course course settings object * @param stdClass $context context object * @param string $component the name of the component we are serving files for. * @param string $filearea the name of the file area. * @param array $args the remaining bits of the file path. * @param bool $forcedownload whether the user must be forced to download the file. */ function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload) { global $DB, $CFG; if ($filearea === 'questiontext_preview') { $component = array_shift($args); $questionid = array_shift($args); component_callback($component, 'questiontext_preview_pluginfile', array($context, $questionid, $args, $forcedownload)); send_file_not_found(); } list($context, $course, $cm) = get_context_info_array($context->id); require_login($course, false, $cm); if ($filearea === 'export') { require_once $CFG->dirroot . '/question/editlib.php'; $contexts = new question_edit_contexts($context); // check export capability $contexts->require_one_edit_tab_cap('export'); $category_id = (int) array_shift($args); $format = array_shift($args); $cattofile = array_shift($args); $contexttofile = array_shift($args); $filename = array_shift($args); // load parent class for import/export require_once $CFG->dirroot . '/question/format.php'; require_once $CFG->dirroot . '/question/editlib.php'; require_once $CFG->dirroot . '/question/format/' . $format . '/format.php'; $classname = 'qformat_' . $format; if (!class_exists($classname)) { send_file_not_found(); } $qformat = new $classname(); if (!($category = $DB->get_record('question_categories', array('id' => $category_id)))) { send_file_not_found(); } $qformat->setCategory($category); $qformat->setContexts($contexts->having_one_edit_tab_cap('export')); $qformat->setCourse($course); if ($cattofile == 'withcategories') { $qformat->setCattofile(true); } else { $qformat->setCattofile(false); } if ($contexttofile == 'withcontexts') { $qformat->setContexttofile(true); } else { $qformat->setContexttofile(false); } if (!$qformat->exportpreprocess()) { send_file_not_found(); print_error('exporterror', 'question', $thispageurl->out()); } // export data to moodle file pool if (!($content = $qformat->exportprocess(true))) { send_file_not_found(); } send_file($content, $filename, 0, 0, true, true, $qformat->mime_type()); } $qubaid = (int) array_shift($args); $slot = (int) array_shift($args); $module = $DB->get_field('question_usages', 'component', array('id' => $qubaid)); if ($module === 'core_question_preview') { require_once $CFG->dirroot . '/question/previewlib.php'; return question_preview_question_pluginfile($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload); } else { $dir = get_component_directory($module); if (!file_exists("{$dir}/lib.php")) { send_file_not_found(); } include_once "{$dir}/lib.php"; $filefunction = $module . '_question_pluginfile'; if (!function_exists($filefunction)) { send_file_not_found(); } $filefunction($course, $context, $component, $filearea, $qubaid, $slot, $args, $forcedownload); send_file_not_found(); } }
/** * Assign roles * * This has to be called after enrolments processing. * * @param mixed $data * @return void */ public function process_assignment($data) { global $DB; $data = (object) $data; // Check roleid, userid are one of the mapped ones if (!($newroleid = $this->get_mappingid('role', $data->roleid))) { return; } if (!($newuserid = $this->get_mappingid('user', $data->userid))) { return; } if (!$DB->record_exists('user', array('id' => $newuserid, 'deleted' => 0))) { // Only assign roles to not deleted users return; } if (!($contextid = $this->task->get_contextid())) { return; } if (empty($data->component)) { // assign standard manual roles // TODO: role_assign() needs one userid param to be able to specify our restore userid role_assign($newroleid, $newuserid, $contextid); } else { if (strpos($data->component, 'enrol_') === 0) { // Deal with enrolment roles - ignore the component and just find out the instance via new id, // it is possible that enrolment was restored using different plugin type. if (!isset($this->plugins)) { $this->plugins = enrol_get_plugins(true); } if ($enrolid = $this->get_mappingid('enrol', $data->itemid)) { if ($instance = $DB->get_record('enrol', array('id' => $enrolid))) { if (isset($this->plugins[$instance->enrol])) { $this->plugins[$instance->enrol]->restore_role_assignment($instance, $newroleid, $newuserid, $contextid); } } } } else { $data->roleid = $newroleid; $data->userid = $newuserid; $data->contextid = $contextid; $dir = core_component::get_component_directory($data->component); if ($dir and is_dir($dir)) { if (component_callback($data->component, 'restore_role_assignment', array($this, $data), true)) { return; } } // Bad luck, plugin could not restore the data, let's add normal membership. role_assign($data->roleid, $data->userid, $data->contextid); $message = "Restore of '{$data->component}/{$data->itemid}' role assignments is not supported, using manual role assignments instead."; $this->log($message, backup::LOG_WARNING); } } }
$url->param('popup', $popup); } $PAGE->set_url($url); $PAGE->set_context($context); if ($popup) { $PAGE->set_pagelayout('popup'); } $params = array('contextid' => $contextid, 'component' => $component, 'ratingarea' => $ratingarea, 'itemid' => $itemid, 'scaleid' => $scaleid); if (!has_capability('moodle/rating:view', $context) || !component_callback($component, 'rating_can_see_item_ratings', array($params), true)) { print_error('noviewrate', 'rating'); } $canviewallratings = has_capability('moodle/rating:viewall', $context); switch ($sort) { case 'firstname': $sqlsort = "u.firstname ASC"; break; case 'rating': $sqlsort = "r.rating ASC"; break; default: $sqlsort = "r.timemodified ASC"; } $scalemenu = make_grades_menu($scaleid); $strrating = get_string('rating', 'rating'); $strname = get_string('name');