function definition() { global $CFG; $mform =& $this->_form; //$mform->addElement('html', get_string('unplagexplain', 'plagiarism_unplag')); $mform->addElement('checkbox', 'unplag_use', get_string('useunplag', 'plagiarism_unplag')); $mform->addElement('text', 'unplag_client_id', get_string('unplag_client_id', 'plagiarism_unplag')); $mform->addHelpButton('unplag_client_id', 'unplag_client_id', 'plagiarism_unplag'); $mform->addRule('unplag_client_id', null, 'required', null, 'client'); $mform->setType('unplag_client_id', PARAM_TEXT); $mform->addElement('text', 'unplag_api_secret', get_string('unplag_api_secret', 'plagiarism_unplag')); $mform->addHelpButton('unplag_api_secret', 'unplag_api_secret', 'plagiarism_unplag'); $mform->addRule('unplag_api_secret', null, 'required', null, 'client'); $mform->setType('unplag_api_secret', PARAM_TEXT); $mform->addElement('text', 'unplag_lang', get_string('unplag_lang', 'plagiarism_unplag')); $mform->addHelpButton('unplag_lang', 'unplag_lang', 'plagiarism_unplag'); $mform->addRule('unplag_lang', null, 'required', null, 'client'); $mform->setDefault('unplag_lang', 'en-US'); $mform->setType('unplag_lang', PARAM_TEXT); $mform->addElement('textarea', 'unplag_student_disclosure', get_string('studentdisclosure', 'plagiarism_unplag'), 'wrap="virtual" rows="6" cols="50"'); $mform->addHelpButton('unplag_student_disclosure', 'studentdisclosure', 'plagiarism_unplag'); $mform->setDefault('unplag_student_disclosure', get_string('studentdisclosuredefault', 'plagiarism_unplag')); $mform->setType('unplag_student_disclosure', PARAM_TEXT); $mods = core_component::get_plugin_list('mod'); foreach ($mods as $mod => $modname) { if (plugin_supports('mod', $mod, FEATURE_PLAGIARISM)) { $modstring = 'unplag_enable_mod_' . $mod; $mform->addElement('checkbox', $modstring, get_string('unplag_enableplugin', 'plagiarism_unplag', $mod)); } } $this->add_action_buttons(true); }
/** * Returns instances of enrol plugins * @param bool $enabled return enabled only * @return array of enrol plugins name=>instance */ function enrol_get_plugins($enabled) { global $CFG; $result = array(); if ($enabled) { // sorted by enabled plugin order $enabled = explode(',', $CFG->enrol_plugins_enabled); $plugins = array(); foreach ($enabled as $plugin) { $plugins[$plugin] = "{$CFG->dirroot}/enrol/{$plugin}"; } } else { // sorted alphabetically $plugins = core_component::get_plugin_list('enrol'); ksort($plugins); } foreach ($plugins as $plugin => $location) { if (!file_exists("{$location}/lib.php")) { continue; } include_once "{$location}/lib.php"; $class = "enrol_{$plugin}_plugin"; if (!class_exists($class)) { continue; } $result[$plugin] = new $class(); } return $result; }
function scorm_report_list($context) { global $CFG; static $reportlist; if (!empty($reportlist)) { return $reportlist; } $installed = core_component::get_plugin_list('scormreport'); foreach ($installed as $reportname => $notused) { // Moodle 2.8+ style of autoloaded classes. $classname = "scormreport_{$reportname}\\report"; if (class_exists($classname)) { $report = new $classname(); if ($report->canview($context)) { $reportlist[] = $reportname; } continue; } // Legacy style of naming classes. $pluginfile = $CFG->dirroot . '/mod/scorm/report/' . $reportname . '/report.php'; if (is_readable($pluginfile)) { debugging("Please use autoloaded classnames for your plugin. Refer MDL-46469 for details", DEBUG_DEVELOPER); include_once $pluginfile; $reportclassname = "scorm_{$reportname}_report"; if (class_exists($reportclassname)) { $report = new $reportclassname(); if ($report->canview($context)) { $reportlist[] = $reportname; } } } } return $reportlist; }
public function test_get_course_formats() { $result = tool_uploadcourse_helper::get_course_formats(); $this->assertSame(array_keys(core_component::get_plugin_list('format')), $result); // Should be similar as first result, as cached. $this->assertSame($result, tool_uploadcourse_helper::get_course_formats()); }
/** * Tests the backup and restore of single activity to same course (duplicate) * when it contains fields and views. */ public function test_duplicate() { global $DB, $CFG; $this->resetAfterTest(true); $this->setAdminUser(); $generator = $this->getDataGenerator(); $dataformgenerator = $generator->get_plugin_generator('mod_dataform'); // Create a course. $course = $generator->create_course(); // DATAFORM 1. $params = array('course' => $course->id, 'grade' => 100); $dataform1 = $dataformgenerator->create_instance($params); $df1 = mod_dataform_dataform::instance($dataform1->id); // Add fields. $fieldtypes = array_keys(core_component::get_plugin_list('dataformfield')); $fieldtypescount = count($fieldtypes); foreach ($fieldtypes as $type) { $df1->field_manager->add_field($type); } // Add views. $viewtypes = array_keys(core_component::get_plugin_list('dataformview')); $viewtypescount = count($viewtypes); foreach ($viewtypes as $type) { $df1->view_manager->add_view($type); } // Fetch the grade item. $params = array('itemtype' => 'mod', 'itemmodule' => 'dataform', 'iteminstance' => $dataform1->id, 'courseid' => $course->id, 'itemnumber' => 0); $gradeitem1 = grade_item::fetch($params); // Check number of dataforms. $this->assertEquals(1, $DB->count_records('dataform')); // Check number of fields. $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields')); $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform1->id))); // Check number of views. $this->assertEquals($viewtypescount, $DB->count_records('dataform_views')); $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform1->id))); // Check number of filters. // $this->assertEquals(2, $DB->count_records('dataform_filters')); // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform1->id)));. // DUPLICATE the dataform instance. $dataform2 = $dataformgenerator->duplicate_instance($course, $dataform1->cmid); // Check number of dataforms. $this->assertEquals(2, $DB->count_records('dataform')); // Check duplication of fields. $this->assertEquals($fieldtypescount * 2, $DB->count_records('dataform_fields')); $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform1->id))); $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform2->id))); // Check duplication of views. $this->assertEquals($viewtypescount * 2, $DB->count_records('dataform_views')); $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform1->id))); $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform2->id))); // Check number of filters. // $this->assertEquals(4, $DB->count_records('dataform_filters'); // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform1->id)); // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform2->id));. // Dataform cleanup. $dataformgenerator->delete_all_instances(); }
/** * Test field events for standard types. */ public function test_field_events() { $this->setAdminUser(); $df = $this->get_a_dataform(); $fieldtypes = array_keys(core_component::get_plugin_list('dataformfield')); foreach ($fieldtypes as $type) { $this->try_crud_field($type, $df); } }
/** * Returns a list of calendar typess available for use. * * @return array the list of calendar types */ public static function get_list_of_calendar_types() { $calendars = array(); $calendardirs = \core_component::get_plugin_list('calendartype'); foreach ($calendardirs as $name => $location) { $calendars[$name] = get_string('name', "calendartype_{$name}"); } return $calendars; }
public function test_get_submission_plugins() { $this->setUser($this->editingteachers[0]); $assign = $this->create_instance(); $installedplugins = array_keys(core_component::get_plugin_list('assignsubmission')); foreach ($assign->get_submission_plugins() as $plugin) { $this->assertContains($plugin->get_type(), $installedplugins, 'Submission plugin not in list of installed plugins'); } }
/** * Is this the last plugin in the list? * * @return bool */ public final function is_last() { $lastindex = count(core_component::get_plugin_list($this->get_subtype())) - 1; $currentindex = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder'); if ($lastindex == $currentindex) { return true; } return false; }
/** * Install the plugin. */ function xmldb_dataform_install() { // Enable existing field plugins. $type = 'dataformfield'; $enabled = array_keys(core_component::get_plugin_list($type)); set_config("enabled_{$type}", implode(',', $enabled), 'mod_dataform'); // Enable existing view plugins. $type = 'dataformview'; $enabled = array_keys(core_component::get_plugin_list($type)); set_config("enabled_{$type}", implode(',', $enabled), 'mod_dataform'); }
/** * Returns an array of reports to which the current user has access to. * @return array reports are ordered as they should be for display in tabs. */ function rcontent_report_list() { global $DB; static $reportlist = null; if (!is_null($reportlist)) { return $reportlist; } $reportdirs = core_component::get_plugin_list('rcontent'); // Add any reports, which are on disc but not in the DB, on the end. foreach ($reportdirs as $reportname => $notused) { $reportlist[] = $reportname; } return $reportlist; }
/** * Get a list of services available in this Moodle installation. * * @return array plugin name => array('name' => '\class\implementing\service') */ public static function service_list() { global $CFG; $result = array(); foreach (\core_component::get_plugin_types() as $plugintype => $fulldir) { foreach (\core_component::get_plugin_list($plugintype) as $name => $dir) { $frankenstyle = $plugintype . '_' . $name; if ($services = self::get_services($frankenstyle)) { $result[$frankenstyle] = $services; } } } return $result; }
public function definition() { $mform =& $this->_form; $mform->addElement('html', get_string('urkundexplain', 'plagiarism_urkund')); $mform->addElement('checkbox', 'urkund_use', get_string('useurkund', 'plagiarism_urkund')); $mform->addElement('text', 'urkund_api', get_string('urkund_api', 'plagiarism_urkund')); $mform->addHelpButton('urkund_api', 'urkund_api', 'plagiarism_urkund'); $mform->addRule('urkund_api', null, 'required', null, 'client'); $mform->setDefault('urkund_api', 'https://secure.urkund.com/api/submissions'); $mform->setType('urkund_api', PARAM_URL); $mform->addElement('text', 'urkund_username', get_string('urkund_username', 'plagiarism_urkund')); $mform->addHelpButton('urkund_username', 'urkund_username', 'plagiarism_urkund'); $mform->addRule('urkund_username', null, 'required', null, 'client'); $mform->setType('urkund_username', PARAM_TEXT); $mform->addElement('passwordunmask', 'urkund_password', get_string('urkund_password', 'plagiarism_urkund')); $mform->addHelpButton('urkund_password', 'urkund_password', 'plagiarism_urkund'); $mform->addRule('urkund_password', null, 'required', null, 'client'); $mform->setType('urkund_password', PARAM_TEXT); $mform->addElement('text', 'urkund_lang', get_string('urkund_lang', 'plagiarism_urkund')); $mform->addHelpButton('urkund_lang', 'urkund_lang', 'plagiarism_urkund'); $mform->addRule('urkund_lang', null, 'required', null, 'client'); $mform->setDefault('urkund_lang', 'en-US'); $mform->setType('urkund_lang', PARAM_TEXT); $mform->addElement('textarea', 'urkund_student_disclosure', get_string('studentdisclosure', 'plagiarism_urkund'), 'wrap="virtual" rows="6" cols="50"'); $mform->addHelpButton('urkund_student_disclosure', 'studentdisclosure', 'plagiarism_urkund'); $mform->setDefault('urkund_student_disclosure', get_string('studentdisclosuredefault', 'plagiarism_urkund')); $mform->setType('urkund_student_disclosure', PARAM_TEXT); $mform->addElement('checkbox', 'urkund_optout', get_string('urkund_enableoptout', 'plagiarism_urkund'), '<br/>' . get_string('urkund_enableoptoutdesc', 'plagiarism_urkund')); $mform->setDefault('urkund_optout', true); $mform->addElement('text', 'urkund_wordcount', get_string('wordcount', 'plagiarism_urkund')); $mform->addHelpButton('urkund_wordcount', 'wordcount', 'plagiarism_urkund'); $mform->setType('urkund_wordcount', PARAM_INT); $mform->addRule('urkund_wordcount', null, 'required', null, 'client'); $mform->setDefault('urkund_wordcount', '50'); $mods = core_component::get_plugin_list('mod'); foreach ($mods as $mod => $modname) { if (plugin_supports('mod', $mod, FEATURE_PLAGIARISM)) { $modstring = 'urkund_enable_mod_' . $mod; $mform->addElement('checkbox', $modstring, get_string('urkund_enableplugin', 'plagiarism_urkund', $mod)); if ($modname == 'assign') { $mform->setDefault($modstring, 1); } } } $this->add_action_buttons(true); }
/** * Returns all the plugins having tests * @param string $testtype The kind of test we are looking for * @return array all the plugins having tests */ private static function get_all_plugins_with_tests($testtype) { $pluginswithtests = array(); $plugintypes = core_component::get_plugin_types(); ksort($plugintypes); foreach ($plugintypes as $type => $unused) { $plugs = core_component::get_plugin_list($type); ksort($plugs); foreach ($plugs as $plug => $fullplug) { // Look for tests recursively if (self::directory_has_tests($fullplug, $testtype)) { $pluginswithtests[$type . '_' . $plug] = $fullplug; } } } return $pluginswithtests; }
/** * Load all the blocks information needed for a given path within moodle2 backup * * This function, given one full path (course, activities/xxxx) will look for all the * blocks existing in the backup file, returning one array used to build the * proper restore plan by the @restore_plan_builder */ public static function get_blocks_from_path($path) { global $DB; $blocks = array(); // To return results static $availableblocks = array(); // Get and cache available blocks if (empty($availableblocks)) { $availableblocks = array_keys(core_component::get_plugin_list('block')); } $path = $path . '/blocks'; // Always look under blocks subdir if (!is_dir($path)) { return array(); } if (!($dir = opendir($path))) { return array(); } while (false !== ($file = readdir($dir))) { if ($file == '.' || $file == '..') { // Skip dots continue; } if (is_dir($path . '/' . $file)) { // Dir found, check it's a valid block if (!file_exists($path . '/' . $file . '/block.xml')) { // Skip if xml file not found continue; } // Extract block name $blockname = preg_replace('/(.*)_\\d+/', '\\1', $file); // Check block exists and is installed if (in_array($blockname, $availableblocks) && $DB->record_exists('block', array('name' => $blockname))) { $blocks[$path . '/' . $file] = $blockname; } } } closedir($dir); return $blocks; }
function scorm_report_list($context) { global $CFG; static $reportlist; if (!empty($reportlist)) { return $reportlist; } $installed = core_component::get_plugin_list('scormreport'); foreach ($installed as $reportname => $notused) { $pluginfile = $CFG->dirroot . '/mod/scorm/report/' . $reportname . '/report.php'; if (is_readable($pluginfile)) { include_once $pluginfile; $reportclassname = "scorm_{$reportname}_report"; if (class_exists($reportclassname)) { $report = new $reportclassname(); if ($report->canview($context)) { $reportlist[] = $reportname; } } } } return $reportlist; }
/** * Returns a list of all components installed on the server * * @return array (string)legacyname => (string)frankenstylename */ public static function list_components() { $list['moodle'] = 'core'; $coresubsystems = core_component::get_core_subsystems(); ksort($coresubsystems); // should be but just in case foreach ($coresubsystems as $name => $location) { $list[$name] = 'core_' . $name; } $plugintypes = core_component::get_plugin_types(); foreach ($plugintypes as $type => $location) { $pluginlist = core_component::get_plugin_list($type); foreach ($pluginlist as $name => $ununsed) { if ($type == 'mod') { // Plugin names are now automatically validated. $list[$name] = $type . '_' . $name; } else { $list[$type . '_' . $name] = $type . '_' . $name; } } } return $list; }
public function definition() { $mform = $this->_form; $behaviour = array('deferredfeedback' => 'Deferred feedback', 'adaptive' => 'Adaptive', 'adaptivenopenalty' => 'Adaptive (no penalties)'); $qtypes = core_component::get_plugin_list('qtype'); foreach ($qtypes as $qtype => $notused) { $qtypes[$qtype] = get_string('pluginname', 'qtype_' . $qtype); } $mform->addElement('header', 'h1', 'Either extract a specific question_session'); $mform->addElement('text', 'attemptid', 'Quiz attempt id', array('size' => '10')); $mform->setType('attemptid', PARAM_INT); $mform->addElement('text', 'questionid', 'Question id', array('size' => '10')); $mform->setType('questionid', PARAM_INT); $mform->addElement('header', 'h2', 'Or find and extract an example by type'); $mform->addElement('select', 'behaviour', 'Behaviour', $behaviour); $mform->setType('behaviour', PARAM_ALPHA); $mform->addElement('text', 'statehistory', 'State history', array('size' => '10')); $mform->setType('statehistory', PARAM_RAW); $mform->addElement('select', 'qtype', 'Question type', $qtypes); $mform->setType('qtype', PARAM_PLUGIN); $mform->addElement('text', 'extratests', 'Extra conditions', array('size' => '50')); $mform->setType('extratests', PARAM_RAW); $this->add_action_buttons(false, 'Create test case'); }
/** * Returns the list of installed grading plugins together, optionally extended * with a simple direct grading. * * @param bool $includenone should the 'Simple direct grading' be included * @return array of the (string)name => (string)localized title of the method */ public static function available_methods($includenone = true) { if ($includenone) { $list = array('' => get_string('gradingmethodnone', 'core_grading')); } else { $list = array(); } foreach (core_component::get_plugin_list('gradingform') as $name => $location) { $list[$name] = get_string('pluginname', 'gradingform_' . $name); } return $list; }
protected function add_subplugin_structure($subplugintype, $element) { global $CFG; // Check the requested subplugintype is a valid one $subpluginsfile = $CFG->dirroot . '/mod/' . $this->task->get_modulename() . '/db/subplugins.php'; if (!file_exists($subpluginsfile)) { throw new restore_step_exception('activity_missing_subplugins_php_file', $this->task->get_modulename()); } include $subpluginsfile; if (!array_key_exists($subplugintype, $subplugins)) { throw new restore_step_exception('incorrect_subplugin_type', $subplugintype); } // Get all the restore path elements, looking across all the subplugin dirs $subpluginsdirs = core_component::get_plugin_list($subplugintype); foreach ($subpluginsdirs as $name => $subpluginsdir) { $classname = 'restore_' . $subplugintype . '_' . $name . '_subplugin'; $restorefile = $subpluginsdir . '/backup/moodle2/' . $classname . '.class.php'; if (file_exists($restorefile)) { require_once $restorefile; $restoresubplugin = new $classname($subplugintype, $name, $this); // Add subplugin paths to the step $this->prepare_pathelements($restoresubplugin->define_subplugin_structure($element)); } } }
/** * Returns hash of all versions including core and all plugins. * * This is relatively slow and not fully cached, use with care! * * @return string sha1 hash */ public static function get_all_versions_hash() { global $CFG; self::init(); $versions = array(); // Main version first. $versions['core'] = self::fetch_core_version(); // The problem here is tha the component cache might be stable, // we want this to work also on frontpage without resetting the component cache. $usecache = false; if (CACHE_DISABLE_ALL or defined('IGNORE_COMPONENT_CACHE') and IGNORE_COMPONENT_CACHE) { $usecache = true; } // Now all plugins. $plugintypes = core_component::get_plugin_types(); foreach ($plugintypes as $type => $typedir) { if ($usecache) { $plugs = core_component::get_plugin_list($type); } else { $plugs = self::fetch_plugins($type, $typedir); } foreach ($plugs as $plug => $fullplug) { $plugin = new stdClass(); $plugin->version = null; $module = $plugin; @(include $fullplug . '/version.php'); $versions[$type . '_' . $plug] = $plugin->version; } } return sha1(serialize($versions)); }
/** * Quiz module upgrade function. * @param string $oldversion the version we are upgrading from. */ function xmldb_quiz_upgrade($oldversion) { global $CFG, $DB; $dbman = $DB->get_manager(); // Moodle v2.2.0 release upgrade line. // Put any upgrade step following this. if ($oldversion < 2011120700) { // Define field lastcron to be dropped from quiz_reports. $table = new xmldb_table('quiz_reports'); $field = new xmldb_field('lastcron'); // Conditionally launch drop field lastcron. if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } // Quiz savepoint reached. upgrade_mod_savepoint(true, 2011120700, 'quiz'); } if ($oldversion < 2011120701) { // Define field cron to be dropped from quiz_reports. $table = new xmldb_table('quiz_reports'); $field = new xmldb_field('cron'); // Conditionally launch drop field cron. if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } // Quiz savepoint reached. upgrade_mod_savepoint(true, 2011120701, 'quiz'); } if ($oldversion < 2011120703) { // Track page of quiz attempts. $table = new xmldb_table('quiz_attempts'); $field = new xmldb_field('currentpage', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2011120703, 'quiz'); } if ($oldversion < 2012030901) { // Configuration option for navigation method. $table = new xmldb_table('quiz'); $field = new xmldb_field('navmethod', XMLDB_TYPE_CHAR, '16', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 'free'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2012030901, 'quiz'); } if ($oldversion < 2012040198) { // This step was added later. In MDL-32727, it was found that adding the // unique index on quiz-userid-attempt sometimes failed because of // duplicate entries {quizid}-{userid}-{attempt}. We do two things to // prevent these problems. First, here, we delete all preview attempts. // This code is an approximate copy-and-paste from // question_engine_data_mapper::delete_questions_usage_by_activities // Note that, for simplicity, the MySQL performance hack has been removed. // Since this code is for upgrade only, performance in not so critical, // where as simplicity of testing the code is. // Note that there is a limit to how far I am prepared to go in eliminating // all calls to library functions in this upgrade code. The only library // function still being used in question_engine::get_all_response_file_areas(); // I think it is pretty safe not to inline it here. // Get a list of response variables that have files. require_once($CFG->dirroot . '/question/type/questiontypebase.php'); $variables = array(); foreach (core_component::get_plugin_list('qtype') as $qtypename => $path) { $file = $path . '/questiontype.php'; if (!is_readable($file)) { continue; } include_once($file); $class = 'qtype_' . $qtypename; if (!class_exists($class)) { continue; } $qtype = new $class(); if (!method_exists($qtype, 'response_file_areas')) { continue; } $variables += $qtype->response_file_areas(); } // Conver that to a list of actual file area names. $fileareas = array(); foreach (array_unique($variables) as $variable) { $fileareas[] = 'response_' . $variable; } // No point checking if this is empty as an optimisation, because essay // has response file areas, so the array will never be empty. // Get all the contexts where there are previews. $contextids = $DB->get_records_sql_menu(" SELECT DISTINCT qu.contextid, 1 FROM {question_usages} qu JOIN {quiz_attempts} quiza ON quiza.uniqueid = qu.id WHERE quiza.preview = 1"); // Loop over contexts and files areas, deleting all files. $fs = get_file_storage(); foreach ($contextids as $contextid => $notused) { foreach ($fileareas as $filearea) { upgrade_set_timeout(300); $fs->delete_area_files_select($contextid, 'question', $filearea, "IN (SELECT qas.id FROM {question_attempt_steps} qas JOIN {question_attempts} qa ON qa.id = qas.questionattemptid JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid WHERE quiza.preview = 1)"); } } // Now delete the question data associated with the previews. $DB->delete_records_select('question_attempt_step_data', "attemptstepid IN ( SELECT qas.id FROM {question_attempt_steps} qas JOIN {question_attempts} qa ON qa.id = qas.questionattemptid JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid WHERE quiza.preview = 1)"); $DB->delete_records_select('question_attempt_steps', "questionattemptid IN ( SELECT qa.id FROM {question_attempts} qa JOIN {quiz_attempts} quiza ON quiza.uniqueid = qa.questionusageid WHERE quiza.preview = 1)"); $DB->delete_records_select('question_attempts', "{question_attempts}.questionusageid IN ( SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)"); $DB->delete_records_select('question_usages', "{question_usages}.id IN ( SELECT uniqueid FROM {quiz_attempts} WHERE preview = 1)"); // Finally delete the previews. $DB->delete_records('quiz_attempts', array('preview' => 1)); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040198, 'quiz'); } if ($oldversion < 2012040199) { // This step was added later. In MDL-32727, it was found that adding the // unique index on quiz-userid-attempt sometimes failed because of // duplicate entries {quizid}-{userid}-{attempt}. // Here, if there are still duplicate entires, we renumber the values in // the attempt column. // Load all the problem quiz attempts. $problems = $DB->get_recordset_sql(' SELECT qa.id, qa.quiz, qa.userid, qa.attempt FROM {quiz_attempts} qa JOIN ( SELECT DISTINCT quiz, userid FROM {quiz_attempts} GROUP BY quiz, userid, attempt HAVING COUNT(1) > 1 ) problems_view ON problems_view.quiz = qa.quiz AND problems_view.userid = qa.userid ORDER BY qa.quiz, qa.userid, qa.attempt, qa.id'); // Renumber them. $currentquiz = null; $currentuserid = null; $attempt = 1; foreach ($problems as $problem) { if ($problem->quiz !== $currentquiz || $problem->userid !== $currentuserid) { $currentquiz = $problem->quiz; $currentuserid = $problem->userid; $attempt = 1; } if ($attempt != $problem->attempt) { $DB->set_field('quiz_attempts', 'attempt', $attempt, array('id' => $problem->id)); } $attempt += 1; } $problems->close(); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040199, 'quiz'); } if ($oldversion < 2012040200) { // Define index userid to be dropped form quiz_attempts $table = new xmldb_table('quiz_attempts'); $index = new xmldb_index('userid', XMLDB_INDEX_NOTUNIQUE, array('userid')); // Conditionally launch drop index quiz-userid-attempt. if ($dbman->index_exists($table, $index)) { $dbman->drop_index($table, $index); } // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040200, 'quiz'); } if ($oldversion < 2012040201) { // Define key userid (foreign) to be added to quiz_attempts. $table = new xmldb_table('quiz_attempts'); $key = new xmldb_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id')); // Launch add key userid. $dbman->add_key($table, $key); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040201, 'quiz'); } if ($oldversion < 2012040202) { // Define index quiz-userid-attempt (unique) to be added to quiz_attempts. $table = new xmldb_table('quiz_attempts'); $index = new xmldb_index('quiz-userid-attempt', XMLDB_INDEX_UNIQUE, array('quiz', 'userid', 'attempt')); // Conditionally launch add index quiz-userid-attempt. if (!$dbman->index_exists($table, $index)) { $dbman->add_index($table, $index); } // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040202, 'quiz'); } if ($oldversion < 2012040203) { // Define field state to be added to quiz_attempts. $table = new xmldb_table('quiz_attempts'); $field = new xmldb_field('state', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'inprogress', 'preview'); // Conditionally launch add field state. if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040203, 'quiz'); } if ($oldversion < 2012040204) { // Update quiz_attempts.state for finished attempts. $DB->set_field_select('quiz_attempts', 'state', 'finished', 'timefinish > 0'); // Other, more complex transitions (basically abandoned attempts), will // be handled by cron later. // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040204, 'quiz'); } if ($oldversion < 2012040205) { // Define field overduehandling to be added to quiz. $table = new xmldb_table('quiz'); $field = new xmldb_field('overduehandling', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, 'autoabandon', 'timelimit'); // Conditionally launch add field overduehandling. if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040205, 'quiz'); } if ($oldversion < 2012040206) { // Define field graceperiod to be added to quiz. $table = new xmldb_table('quiz'); $field = new xmldb_field('graceperiod', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'overduehandling'); // Conditionally launch add field graceperiod. if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012040206, 'quiz'); } // Moodle v2.3.0 release upgrade line // Put any upgrade step following this if ($oldversion < 2012061702) { // MDL-32791 somebody reported having nonsense rows in their // quiz_question_instances which caused various problems. These rows // are meaningless, hence this upgrade step to clean them up. $DB->delete_records('quiz_question_instances', array('question' => 0)); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012061702, 'quiz'); } if ($oldversion < 2012061703) { // MDL-34702 the questiondecimalpoints column was created with default -2 // when it should have been -1, and no-one has noticed in the last 2+ years! // Changing the default of field questiondecimalpoints on table quiz to -1. $table = new xmldb_table('quiz'); $field = new xmldb_field('questiondecimalpoints', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '-1', 'decimalpoints'); // Launch change of default for field questiondecimalpoints. $dbman->change_field_default($table, $field); // Correct any wrong values. $DB->set_field('quiz', 'questiondecimalpoints', -1, array('questiondecimalpoints' => -2)); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2012061703, 'quiz'); } if ($oldversion < 2012100801) { // Define field timecheckstate to be added to quiz_attempts $table = new xmldb_table('quiz_attempts'); $field = new xmldb_field('timecheckstate', XMLDB_TYPE_INTEGER, '10', null, null, null, '0', 'timemodified'); // Conditionally launch add field timecheckstate if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Define index state-timecheckstate (not unique) to be added to quiz_attempts $table = new xmldb_table('quiz_attempts'); $index = new xmldb_index('state-timecheckstate', XMLDB_INDEX_NOTUNIQUE, array('state', 'timecheckstate')); // Conditionally launch add index state-timecheckstate if (!$dbman->index_exists($table, $index)) { $dbman->add_index($table, $index); } // Overdue cron no longer needs these unset_config('overduelastrun', 'quiz'); unset_config('overduedoneto', 'quiz'); // Update timecheckstate on all open attempts require_once($CFG->dirroot . '/mod/quiz/locallib.php'); quiz_update_open_attempts(array()); // quiz savepoint reached upgrade_mod_savepoint(true, 2012100801, 'quiz'); } // Moodle v2.4.0 release upgrade line // Put any upgrade step following this if ($oldversion < 2013031900) { // Quiz manual grading UI should be controlled by mod/quiz:grade, not :viewreports. $DB->set_field('quiz_reports', 'capability', 'mod/quiz:grade', array('name' => 'grading')); // Mod quiz savepoint reached. upgrade_mod_savepoint(true, 2013031900, 'quiz'); } // Moodle v2.5.0 release upgrade line. // Put any upgrade step following this. // Moodle v2.6.0 release upgrade line. // Put any upgrade step following this. if ($oldversion < 2014011300) { // Define key quiz (foreign) to be dropped form quiz_question_instances. $table = new xmldb_table('quiz_question_instances'); $key = new xmldb_key('quiz', XMLDB_KEY_FOREIGN, array('quiz'), 'quiz', array('id')); // Launch drop key quiz. $dbman->drop_key($table, $key); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2014011300, 'quiz'); } if ($oldversion < 2014011301) { // Rename field quiz on table quiz_question_instances to quizid. $table = new xmldb_table('quiz_question_instances'); $field = new xmldb_field('quiz', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'id'); // Launch rename field quiz. $dbman->rename_field($table, $field, 'quizid'); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2014011301, 'quiz'); } if ($oldversion < 2014011302) { // Define key quizid (foreign) to be added to quiz_question_instances. $table = new xmldb_table('quiz_question_instances'); $key = new xmldb_key('quizid', XMLDB_KEY_FOREIGN, array('quizid'), 'quiz', array('id')); // Launch add key quizid. $dbman->add_key($table, $key); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2014011302, 'quiz'); } if ($oldversion < 2014011303) { // Define key question (foreign) to be dropped form quiz_question_instances. $table = new xmldb_table('quiz_question_instances'); $key = new xmldb_key('question', XMLDB_KEY_FOREIGN, array('question'), 'question', array('id')); // Launch drop key question. $dbman->drop_key($table, $key); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2014011303, 'quiz'); } if ($oldversion < 2014011304) { // Rename field question on table quiz_question_instances to questionid. $table = new xmldb_table('quiz_question_instances'); $field = new xmldb_field('question', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'quiz'); // Launch rename field question. $dbman->rename_field($table, $field, 'questionid'); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2014011304, 'quiz'); } if ($oldversion < 2014011305) { // Define key questionid (foreign) to be added to quiz_question_instances. $table = new xmldb_table('quiz_question_instances'); $key = new xmldb_key('questionid', XMLDB_KEY_FOREIGN, array('questionid'), 'question', array('id')); // Launch add key questionid. $dbman->add_key($table, $key); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2014011305, 'quiz'); } if ($oldversion < 2014011306) { // Rename field grade on table quiz_question_instances to maxmark. $table = new xmldb_table('quiz_question_instances'); $field = new xmldb_field('grade', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '0', 'question'); // Launch rename field grade. $dbman->rename_field($table, $field, 'maxmark'); // Quiz savepoint reached. upgrade_mod_savepoint(true, 2014011306, 'quiz'); } return true; }
$heading = get_string('selecttheme', 'admin', $device); if (empty($device)) { // If $CFG->enabledevicedetection is off this will return 'default'. $device = core_useragent::get_device_type(); } $themelocked = theme_is_device_locked($device); $table->id = 'adminthemeselector'; $table->head = array(get_string('theme'), get_string('info')); $themes = array(); if ($themelocked) { $heading = get_string('currenttheme', 'admin'); $themename = theme_get_locked_theme_for_device($device); $themedirectory = core_component::get_plugin_directory('theme', $themename); $themes[$themename] = $themedirectory; } else { $themes = core_component::get_plugin_list('theme'); } foreach ($themes as $themename => $themedir) { // Load the theme config. try { $theme = theme_config::load($themename); } catch (Exception $e) { // Bad theme, just skip it for now. continue; } if ($themename !== $theme->name) { // Obsoleted or broken theme, just skip for now. continue; } if (empty($CFG->themedesignermode) && $theme->hidefromselector) { // The theme doesn't want to be shown in the theme selector and as theme
/** * Used to add in old-style cron functions within plugins that have not been converted to the * new standard API. (The standard API is frankenstyle_name_cron() in lib.php; some types used * cron.php and some used a different name.) * * @param string $plugintype Plugin type e.g. 'report' * @param array $plugins Array from plugin name (e.g. 'report_frog') to function name (e.g. * 'report_frog_cron') for plugin cron functions that were already found using the new API * @return array Revised version of $plugins that adds in any extra plugin functions found by * looking in the older location */ function cron_bc_hack_plugin_functions($plugintype, $plugins) { global $CFG; // mandatory in case it is referenced by include()d PHP script if ($plugintype === 'report') { // Admin reports only - not course report because course report was // never implemented before, so doesn't need BC foreach (core_component::get_plugin_list($plugintype) as $pluginname => $dir) { $component = $plugintype . '_' . $pluginname; if (isset($plugins[$component])) { // We already have detected the function using the new API continue; } if (!file_exists("{$dir}/cron.php")) { // No old style cron file present continue; } include_once "{$dir}/cron.php"; $cronfunction = $component . '_cron'; if (function_exists($cronfunction)) { $plugins[$component] = $cronfunction; } else { debugging("Invalid legacy cron.php detected in {$component}, " . "please use lib.php instead"); } } } else { if (strpos($plugintype, 'grade') === 0) { // Detect old style cron function names // Plugin gradeexport_frog used to use grade_export_frog_cron() instead of // new standard API gradeexport_frog_cron(). Also applies to gradeimport, gradereport foreach (core_component::get_plugin_list($plugintype) as $pluginname => $dir) { $component = $plugintype . '_' . $pluginname; if (isset($plugins[$component])) { // We already have detected the function using the new API continue; } if (!file_exists("{$dir}/lib.php")) { continue; } include_once "{$dir}/lib.php"; $cronfunction = str_replace('grade', 'grade_', $plugintype) . '_' . $pluginname . '_cron'; if (function_exists($cronfunction)) { $plugins[$component] = $cronfunction; } } } } return $plugins; }
/** * Get information export plugins * @param int $courseid * @return array */ public static function get_plugins_export($courseid) { global $CFG; if (self::$exportplugins !== null) { return self::$exportplugins; } $context = context_course::instance($courseid); $exportplugins = array(); if (has_capability('moodle/grade:export', $context)) { foreach (core_component::get_plugin_list('gradeexport') as $plugin => $plugindir) { if (!has_capability('gradeexport/' . $plugin . ':view', $context)) { continue; } $pluginstr = get_string('pluginname', 'gradeexport_' . $plugin); $url = new moodle_url('/grade/export/' . $plugin . '/index.php', array('id' => $courseid)); $exportplugins[$plugin] = new grade_plugin_info($plugin, $url, $pluginstr); } if ($CFG->gradepublishing) { $url = new moodle_url('/grade/export/keymanager.php', array('id' => $courseid)); $exportplugins['keymanager'] = new grade_plugin_info('keymanager', $url, get_string('keymanager', 'grades')); } } if (count($exportplugins) > 0) { asort($exportplugins); self::$exportplugins = $exportplugins; } else { self::$exportplugins = false; } return self::$exportplugins; }
/** * Update courses * * @param array $courses * @since Moodle 2.5 */ public static function update_courses($courses) { global $CFG, $DB; require_once($CFG->dirroot . "/course/lib.php"); $warnings = array(); $params = self::validate_parameters(self::update_courses_parameters(), array('courses' => $courses)); $availablethemes = core_component::get_plugin_list('theme'); $availablelangs = get_string_manager()->get_list_of_translations(); foreach ($params['courses'] as $course) { // Catch any exception while updating course and return as warning to user. try { // Ensure the current user is allowed to run this function. $context = context_course::instance($course['id'], MUST_EXIST); self::validate_context($context); $oldcourse = course_get_format($course['id'])->get_course(); require_capability('moodle/course:update', $context); // Check if user can change category. if (array_key_exists('categoryid', $course) && ($oldcourse->category != $course['categoryid'])) { require_capability('moodle/course:changecategory', $context); $course['category'] = $course['categoryid']; } // Check if the user can change fullname. if (array_key_exists('fullname', $course) && ($oldcourse->fullname != $course['fullname'])) { require_capability('moodle/course:changefullname', $context); } // Check if the user can change shortname. if (array_key_exists('shortname', $course) && ($oldcourse->shortname != $course['shortname'])) { require_capability('moodle/course:changeshortname', $context); } // Check if the user can change the idnumber. if (array_key_exists('idnumber', $course) && ($oldcourse->idnumber != $course['idnumber'])) { require_capability('moodle/course:changeidnumber', $context); } // Check if user can change summary. if (array_key_exists('summary', $course) && ($oldcourse->summary != $course['summary'])) { require_capability('moodle/course:changesummary', $context); } // Summary format. if (array_key_exists('summaryformat', $course) && ($oldcourse->summaryformat != $course['summaryformat'])) { require_capability('moodle/course:changesummary', $context); $course['summaryformat'] = external_validate_format($course['summaryformat']); } // Check if user can change visibility. if (array_key_exists('visible', $course) && ($oldcourse->visible != $course['visible'])) { require_capability('moodle/course:visibility', $context); } // Make sure lang is valid. if (array_key_exists('lang', $course) && empty($availablelangs[$course['lang']])) { throw new moodle_exception('errorinvalidparam', 'webservice', '', 'lang'); } // Make sure theme is valid. if (array_key_exists('forcetheme', $course)) { if (!empty($CFG->allowcoursethemes)) { if (empty($availablethemes[$course['forcetheme']])) { throw new moodle_exception('errorinvalidparam', 'webservice', '', 'forcetheme'); } else { $course['theme'] = $course['forcetheme']; } } } // Make sure completion is enabled before setting it. if (array_key_exists('enabledcompletion', $course) && !completion_info::is_enabled_for_site()) { $course['enabledcompletion'] = 0; } // Make sure maxbytes are less then CFG->maxbytes. if (array_key_exists('maxbytes', $course)) { $course['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $course['maxbytes']); } if (!empty($course['courseformatoptions'])) { foreach ($course['courseformatoptions'] as $option) { if (isset($option['name']) && isset($option['value'])) { $course[$option['name']] = $option['value']; } } } // Update course if user has all required capabilities. update_course((object) $course); } catch (Exception $e) { $warning = array(); $warning['item'] = 'course'; $warning['itemid'] = $course['id']; if ($e instanceof moodle_exception) { $warning['warningcode'] = $e->errorcode; } else { $warning['warningcode'] = $e->getCode(); } $warning['message'] = $e->getMessage(); $warnings[] = $warning; } } $result = array(); $result['warnings'] = $warnings; return $result; }
/** * Get class name for the format * * If course format xxx does not declare class format_xxx, format_legacy will be returned. * This function also includes lib.php file from corresponding format plugin * * @param string $format * @return string */ protected static final function get_class_name($format) { global $CFG; static $classnames = array('site' => 'format_site'); if (!isset($classnames[$format])) { $plugins = core_component::get_plugin_list('format'); $usedformat = self::get_format_or_default($format); if (isset($plugins[$usedformat]) && file_exists($plugins[$usedformat] . '/lib.php')) { require_once $plugins[$usedformat] . '/lib.php'; } $classnames[$format] = 'format_' . $usedformat; if (!class_exists($classnames[$format])) { require_once $CFG->dirroot . '/course/format/formatlegacy.php'; $classnames[$format] = 'format_legacy'; } } return $classnames[$format]; }
/** * Load the plugins from the sub folders under subtype. * * @param string $subtype - either submission or feedback * @return array - The sorted list of plugins */ protected function load_plugins($subtype) { global $CFG; $result = array(); $names = core_component::get_plugin_list($subtype); foreach ($names as $name => $path) { if (file_exists($path . '/locallib.php')) { require_once $path . '/locallib.php'; $shortsubtype = substr($subtype, strlen('assign')); $pluginclass = 'assign_' . $shortsubtype . '_' . $name; $plugin = new $pluginclass($this, $name); if ($plugin instanceof assign_plugin) { $idx = $plugin->get_sort_order(); while (array_key_exists($idx, $result)) { $idx += 1; } $result[$idx] = $plugin; } } } ksort($result); return $result; }
/** * Sets whether a particular active filter should be applied to all strings by * format_string, or just used by format_text. * * @param string $filter The filter name, for example 'tex'. * @param boolean $applytostrings if true, this filter will apply to format_string * and format_text, when it is enabled. */ function filter_set_applies_to_strings($filter, $applytostrings) { $stringfilters = filter_get_string_filters(); $prevfilters = $stringfilters; $allfilters = core_component::get_plugin_list('filter'); if ($applytostrings) { $stringfilters[$filter] = $filter; } else { unset($stringfilters[$filter]); } // Remove missing filters. foreach ($stringfilters as $filter) { if (!isset($allfilters[$filter])) { unset($stringfilters[$filter]); } } if ($prevfilters != $stringfilters) { set_config('stringfilters', implode(',', $stringfilters)); set_config('filterall', !empty($stringfilters)); } }
/** * This function loads all of the front page settings into the settings navigation. * This function is called when the user is on the front page, or $COURSE==$SITE * @param bool $forceopen (optional) * @return navigation_node */ protected function load_front_page_settings($forceopen = false) { global $SITE, $CFG; $course = clone $SITE; $coursecontext = context_course::instance($course->id); // Course context $frontpage = $this->add(get_string('frontpagesettings'), null, self::TYPE_SETTING, null, 'frontpage'); if ($forceopen) { $frontpage->force_open(); } $frontpage->id = 'frontpagesettings'; if ($this->page->user_allowed_editing()) { // Add the turn on/off settings $url = new moodle_url('/course/view.php', array('id' => $course->id, 'sesskey' => sesskey())); if ($this->page->user_is_editing()) { $url->param('edit', 'off'); $editstring = get_string('turneditingoff'); } else { $url->param('edit', 'on'); $editstring = get_string('turneditingon'); } $frontpage->add($editstring, $url, self::TYPE_SETTING, null, null, new pix_icon('i/edit', '')); } if (has_capability('moodle/course:update', $coursecontext)) { // Add the course settings link $url = new moodle_url('/admin/settings.php', array('section' => 'frontpagesettings')); $frontpage->add(get_string('editsettings'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/settings', '')); } // add enrol nodes enrol_add_course_navigation($frontpage, $course); // Manage filters if (has_capability('moodle/filter:manage', $coursecontext) && count(filter_get_available_in_context($coursecontext)) > 0) { $url = new moodle_url('/filter/manage.php', array('contextid' => $coursecontext->id)); $frontpage->add(get_string('filters', 'admin'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/filter', '')); } // View course reports. if (has_capability('moodle/site:viewreports', $coursecontext)) { // Basic capability for listing of reports. $frontpagenav = $frontpage->add(get_string('reports'), null, self::TYPE_CONTAINER, null, 'frontpagereports', new pix_icon('i/stats', '')); $coursereports = core_component::get_plugin_list('coursereport'); foreach ($coursereports as $report => $dir) { $libfile = $CFG->dirroot . '/course/report/' . $report . '/lib.php'; if (file_exists($libfile)) { require_once $libfile; $reportfunction = $report . '_report_extend_navigation'; if (function_exists($report . '_report_extend_navigation')) { $reportfunction($frontpagenav, $course, $coursecontext); } } } $reports = get_plugin_list_with_function('report', 'extend_navigation_course', 'lib.php'); foreach ($reports as $reportfunction) { $reportfunction($frontpagenav, $course, $coursecontext); } } // Backup this course if (has_capability('moodle/backup:backupcourse', $coursecontext)) { $url = new moodle_url('/backup/backup.php', array('id' => $course->id)); $frontpage->add(get_string('backup'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/backup', '')); } // Restore to this course if (has_capability('moodle/restore:restorecourse', $coursecontext)) { $url = new moodle_url('/backup/restorefile.php', array('contextid' => $coursecontext->id)); $frontpage->add(get_string('restore'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/restore', '')); } // Questions require_once $CFG->libdir . '/questionlib.php'; question_extend_settings_navigation($frontpage, $coursecontext)->trim_if_empty(); // Manage files if ($course->legacyfiles == 2 and has_capability('moodle/course:managefiles', $this->context)) { //hiden in new installs $url = new moodle_url('/files/index.php', array('contextid' => $coursecontext->id)); $frontpage->add(get_string('sitelegacyfiles'), $url, self::TYPE_SETTING, null, null, new pix_icon('i/folder', '')); } // Let plugins hook into frontpage navigation. $pluginsfunction = get_plugins_with_function('extend_navigation_frontpage', 'lib.php'); foreach ($pluginsfunction as $plugintype => $plugins) { foreach ($plugins as $pluginfunction) { $pluginfunction($frontpage, $course, $coursecontext); } } return $frontpage; }