public function test_create_content() { global $DB; $this->resetAfterTest(); $this->setAdminUser(); $course = $this->getDataGenerator()->create_course(); $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course)); $wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki'); $page1 = $wikigenerator->create_first_page($wiki); $page2 = $wikigenerator->create_content($wiki); $page3 = $wikigenerator->create_content($wiki, array('title' => 'Custom title', 'tags' => array('Cats', 'mice'))); unset($wiki->cmid); $page4 = $wikigenerator->create_content($wiki, array('tags' => 'Cats, dogs')); $subwikis = $DB->get_records('wiki_subwikis', array('wikiid' => $wiki->id), 'id'); $this->assertEquals(1, count($subwikis)); $subwikiid = key($subwikis); $records = $DB->get_records('wiki_pages', array('subwikiid' => $subwikiid), 'id'); $this->assertEquals(4, count($records)); $this->assertEquals($page1->id, $records[$page1->id]->id); $this->assertEquals($page2->id, $records[$page2->id]->id); $this->assertEquals($page3->id, $records[$page3->id]->id); $this->assertEquals('Custom title', $records[$page3->id]->title); $this->assertEquals(array('Cats', 'mice'), array_values(core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page3->id))); $this->assertEquals(array('Cats', 'dogs'), array_values(core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page4->id))); }
/** * Export this data so it can be used as the context for a mustache template. * * @param renderer_base $output * @return stdClass */ public function export_for_template(renderer_base $output) { global $CFG; require_once $CFG->libdir . '/externallib.php'; $r = new stdClass(); $r->id = (int) $this->record->id; $r->tagcollid = clean_param($this->record->tagcollid, PARAM_INT); $r->rawname = clean_param($this->record->rawname, PARAM_TAG); $r->name = clean_param($this->record->name, PARAM_TAG); $format = clean_param($this->record->descriptionformat, PARAM_INT); list($r->description, $r->descriptionformat) = external_format_text($this->record->description, $format, \context_system::instance()->id, 'core', 'tag', $r->id); $r->flag = clean_param($this->record->flag, PARAM_INT); if (isset($this->record->official)) { $r->official = clean_param($this->record->official, PARAM_INT); } else { $r->official = $this->record->tagtype === 'official' ? 1 : 0; } $url = \core_tag_tag::make_url($r->tagcollid, $r->rawname); $r->viewurl = $url->out(false); $manageurl = new moodle_url('/tag/manage.php', array('sesskey' => sesskey(), 'tagid' => $this->record->id)); $url = new moodle_url($manageurl); $url->param('action', 'changetype'); $url->param('tagtype', $r->official ? 'default' : 'official'); $r->changetypeurl = $url->out(false); $url = new moodle_url($manageurl); $url->param('action', $this->record->flag ? 'resetflag' : 'setflag'); $r->changeflagurl = $url->out(false); return $r; }
/** * Implements callback inplace_editable() allowing to edit values in-place * * @param string $itemtype * @param int $itemid * @param mixed $newvalue * @return \core\output\inplace_editable */ function core_tag_inplace_editable($itemtype, $itemid, $newvalue) { if ($itemtype === 'tagname') { require_capability('moodle/tag:manage', context_system::instance()); $tag = core_tag_tag::get($itemid, '*', MUST_EXIST); $tag->update(array('rawname' => $newvalue)); return new \core_tag\output\tagname($tag); } }
/** * Custom form validation * * @param array $data * @param array $files * @return array */ public function validation($data, $files) { $errors = parent::validation($data, $files); if (isset($data['rawname'])) { $newname = core_text::strtolower($data['rawname']); $tag = $this->_customdata['tag']; if ($tag->name != $newname) { // The name has changed, let's make sure it's not another existing tag. if (core_tag_tag::get_by_name($tag->tagcollid, $newname)) { // Something exists already, so flag an error. $errors['rawname'] = get_string('namesalreadybeeingused', 'tag'); } } } return $errors; }
/** * Constructor * * @param core_tag_tag|stdClass $tag * @param string $component * @param string $itemtype * @param string $content * @param bool $exclusivemode * @param int $fromctx context id where the link was displayed, may be used by callbacks * to display items in the same context first * @param int $ctx context id where we need to search for items * @param int $rec search items in sub contexts as well * @param int $page * @param bool $totalpages */ public function __construct($tag, $component, $itemtype, $content, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0, $totalpages = 1) { $this->record = new stdClass(); $this->tag = $tag; $tagareas = \core_tag_area::get_areas(); if (!isset($tagareas[$itemtype][$component])) { throw new \coding_exception('Tag area for component ' . $component . ' and itemtype ' . $itemtype . ' is not defined'); } $this->tagarea = $tagareas[$itemtype][$component]; $this->record->tagid = $tag->id; $this->record->ta = $this->tagarea->id; $this->record->itemtype = $itemtype; $this->record->component = $component; $a = (object) array('tagarea' => \core_tag_area::display_name($component, $itemtype), 'tag' => \core_tag_tag::make_display_name($tag)); if ($exclusivemode) { $this->record->title = get_string('itemstaggedwith', 'tag', $a); } else { $this->record->title = (string) $a->tagarea; } $this->record->content = $content; $this->record->nextpageurl = null; $this->record->prevpageurl = null; $this->record->exclusiveurl = null; $url = core_tag_tag::make_url($tag->tagcollid, $tag->rawname, $exclusivemode, $fromctx, $ctx, $rec); $urlparams = array('ta' => $this->tagarea->id); if ($totalpages > $page + 1) { $this->record->nextpageurl = new moodle_url($url, $urlparams + array('page' => $page + 1)); } if ($page > 0) { $this->record->prevpageurl = new moodle_url($url, $urlparams + array('page' => $page - 1)); } if (!$exclusivemode && ($totalpages > 1 || $page)) { $this->record->exclusiveurl = new moodle_url($url, $urlparams + array('excl' => 1)); } $this->record->exclusivetext = get_string('exclusivemode', 'tag', $a); $this->record->hascontent = $totalpages > 1 || $page || $content; $this->record->anchor = $component . '_' . $itemtype; }
/** * Implements callback to reset course * * @param stdClass $data * @return boolean|array */ function wiki_reset_userdata($data) { global $CFG, $DB; require_once $CFG->dirroot . '/mod/wiki/pagelib.php'; require_once $CFG->dirroot . "/mod/wiki/locallib.php"; $componentstr = get_string('modulenameplural', 'wiki'); $status = array(); //get the wiki(s) in this course. if (!($wikis = $DB->get_records('wiki', array('course' => $data->courseid)))) { return false; } if (empty($data->reset_wiki_comments) && empty($data->reset_wiki_tags) && empty($data->reset_wiki_pages)) { return $status; } foreach ($wikis as $wiki) { if (!($cm = get_coursemodule_from_instance('wiki', $wiki->id, $data->courseid))) { continue; } $context = context_module::instance($cm->id); // Remove tags or all pages. if (!empty($data->reset_wiki_pages) || !empty($data->reset_wiki_tags)) { // Get subwiki information. $subwikis = wiki_get_subwikis($wiki->id); foreach ($subwikis as $subwiki) { // Get existing pages. if ($pages = wiki_get_page_list($subwiki->id)) { // If the wiki page isn't selected then we are only removing tags. if (empty($data->reset_wiki_pages)) { // Go through each page and delete the tags. foreach ($pages as $page) { core_tag_tag::remove_all_item_tags('mod_wiki', 'wiki_pages', $page->id); } } else { // Otherwise we are removing pages and tags. wiki_delete_pages($context, $pages, $subwiki->id); } } if (!empty($data->reset_wiki_pages)) { // Delete any subwikis. $DB->delete_records('wiki_subwikis', array('id' => $subwiki->id), IGNORE_MISSING); // Delete any attached files. $fs = get_file_storage(); $fs->delete_area_files($context->id, 'mod_wiki', 'attachments'); } } if (!empty($data->reset_wiki_pages)) { $status[] = array('component' => $componentstr, 'item' => get_string('deleteallpages', 'wiki'), 'error' => false); } if (!empty($data->reset_wiki_tags)) { $status[] = array('component' => $componentstr, 'item' => get_string('tagsdeleted', 'wiki'), 'error' => false); } } // Remove all comments. if (!empty($data->reset_wiki_comments) || !empty($data->reset_wiki_pages)) { $DB->delete_records_select('comments', "contextid = ? AND commentarea='wiki_page'", array($context->id)); if (!empty($data->reset_wiki_comments)) { $status[] = array('component' => $componentstr, 'item' => get_string('deleteallcomments'), 'error' => false); } } } return $status; }
public function test_data_saved() { global $DB; $this->resetAfterTest(true); // Create. $mode = tool_uploadcourse_processor::MODE_CREATE_NEW; $updatemode = tool_uploadcourse_processor::UPDATE_NOTHING; $data = array('shortname' => 'c1', 'fullname' => 'Fullname', 'category' => '1', 'visible' => '0', 'startdate' => '8 June 1990', 'idnumber' => '123abc', 'summary' => 'Summary', 'format' => 'weeks', 'theme' => 'afterburner', 'lang' => 'en', 'newsitems' => '7', 'showgrades' => '0', 'showreports' => '1', 'legacyfiles' => '1', 'maxbytes' => '1234', 'groupmode' => '2', 'groupmodeforce' => '1', 'enablecompletion' => '1', 'tags' => 'Cat, Dog', 'role_teacher' => 'Knight', 'role_manager' => 'Jedi', 'enrolment_1' => 'guest', 'enrolment_2' => 'self', 'enrolment_2_roleid' => '1', 'enrolment_3' => 'manual', 'enrolment_3_disable' => '1'); $this->assertFalse($DB->record_exists('course', array('shortname' => 'c1'))); $co = new tool_uploadcourse_course($mode, $updatemode, $data); $this->assertTrue($co->prepare()); $co->proceed(); $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); $course = $DB->get_record('course', array('shortname' => 'c1')); $ctx = context_course::instance($course->id); $this->assertEquals($data['fullname'], $course->fullname); $this->assertEquals($data['category'], $course->category); $this->assertEquals($data['visible'], $course->visible); $this->assertEquals(mktime(0, 0, 0, 6, 8, 1990), $course->startdate); $this->assertEquals($data['idnumber'], $course->idnumber); $this->assertEquals($data['summary'], $course->summary); $this->assertEquals($data['format'], $course->format); $this->assertEquals($data['theme'], $course->theme); $this->assertEquals($data['lang'], $course->lang); $this->assertEquals($data['newsitems'], $course->newsitems); $this->assertEquals($data['showgrades'], $course->showgrades); $this->assertEquals($data['showreports'], $course->showreports); $this->assertEquals($data['legacyfiles'], $course->legacyfiles); $this->assertEquals($data['maxbytes'], $course->maxbytes); $this->assertEquals($data['groupmode'], $course->groupmode); $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce); $this->assertEquals($data['enablecompletion'], $course->enablecompletion); $this->assertEquals($data['tags'], join(', ', core_tag_tag::get_item_tags_array('core', 'course', $course->id))); // Roles. $roleids = array(); $roles = get_all_roles(); foreach ($roles as $role) { $roleids[$role->shortname] = $role->id; } $this->assertEquals('Knight', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher']))); $this->assertEquals('Jedi', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager']))); // Enrolment methods. $enroldata = array(); $instances = enrol_get_instances($course->id, false); $this->assertCount(3, $instances); foreach ($instances as $instance) { $enroldata[$instance->enrol] = $instance; } $this->assertNotEmpty($enroldata['guest']); $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['guest']->status); $this->assertNotEmpty($enroldata['self']); $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid); $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status); $this->assertNotEmpty($enroldata['manual']); $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['manual']->status); // Update existing course. $cat = $this->getDataGenerator()->create_category(); $mode = tool_uploadcourse_processor::MODE_UPDATE_ONLY; $updatemode = tool_uploadcourse_processor::UPDATE_ALL_WITH_DATA_ONLY; $data = array('shortname' => 'c1', 'fullname' => 'Fullname 2', 'category' => $cat->id, 'visible' => '1', 'startdate' => '11 June 1984', 'idnumber' => 'changeidn', 'summary' => 'Summary 2', 'format' => 'topics', 'theme' => 'clean', 'lang' => '', 'newsitems' => '2', 'showgrades' => '1', 'showreports' => '0', 'legacyfiles' => '0', 'maxbytes' => '4321', 'groupmode' => '1', 'groupmodeforce' => '0', 'enablecompletion' => '0', 'role_teacher' => 'Teacher', 'role_manager' => 'Manager', 'enrolment_1' => 'guest', 'enrolment_1_disable' => '1', 'enrolment_2' => 'self', 'enrolment_2_roleid' => '2', 'enrolment_3' => 'manual', 'enrolment_3_delete' => '1'); $this->assertTrue($DB->record_exists('course', array('shortname' => 'c1'))); $co = new tool_uploadcourse_course($mode, $updatemode, $data); $this->assertTrue($co->prepare()); $co->proceed(); $course = $DB->get_record('course', array('shortname' => 'c1')); $ctx = context_course::instance($course->id); $this->assertEquals($data['fullname'], $course->fullname); $this->assertEquals($data['category'], $course->category); $this->assertEquals($data['visible'], $course->visible); $this->assertEquals(mktime(0, 0, 0, 6, 11, 1984), $course->startdate); $this->assertEquals($data['idnumber'], $course->idnumber); $this->assertEquals($data['summary'], $course->summary); $this->assertEquals($data['format'], $course->format); $this->assertEquals($data['theme'], $course->theme); $this->assertEquals($data['lang'], $course->lang); $this->assertEquals($data['newsitems'], $course->newsitems); $this->assertEquals($data['showgrades'], $course->showgrades); $this->assertEquals($data['showreports'], $course->showreports); $this->assertEquals($data['legacyfiles'], $course->legacyfiles); $this->assertEquals($data['maxbytes'], $course->maxbytes); $this->assertEquals($data['groupmode'], $course->groupmode); $this->assertEquals($data['groupmodeforce'], $course->groupmodeforce); $this->assertEquals($data['enablecompletion'], $course->enablecompletion); // Roles. $roleids = array(); $roles = get_all_roles(); foreach ($roles as $role) { $roleids[$role->shortname] = $role->id; } $this->assertEquals('Teacher', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['teacher']))); $this->assertEquals('Manager', $DB->get_field_select('role_names', 'name', 'roleid = :roleid AND contextid = :ctxid', array('ctxid' => $ctx->id, 'roleid' => $roleids['manager']))); // Enrolment methods. $enroldata = array(); $instances = enrol_get_instances($course->id, false); $this->assertCount(2, $instances); foreach ($instances as $instance) { $enroldata[$instance->enrol] = $instance; } $this->assertNotEmpty($enroldata['guest']); $this->assertEquals(ENROL_INSTANCE_DISABLED, $enroldata['guest']->status); $this->assertNotEmpty($enroldata['self']); $this->assertEquals($data['enrolment_2_roleid'], $enroldata['self']->roleid); $this->assertEquals(ENROL_INSTANCE_ENABLED, $enroldata['self']->status); }
/** * Clear a course out completely, deleting all content but don't delete the course itself. * * This function does not verify any permissions. * * Please note this function also deletes all user enrolments, * enrolment instances and role assignments by default. * * $options: * - 'keep_roles_and_enrolments' - false by default * - 'keep_groups_and_groupings' - false by default * * @param int $courseid The id of the course that is being deleted * @param bool $showfeedback Whether to display notifications of each action the function performs. * @param array $options extra options * @return bool true if all the removals succeeded. false if there were any failures. If this * method returns false, some of the removals will probably have succeeded, and others * failed, but you have no way of knowing which. */ function remove_course_contents($courseid, $showfeedback = true, array $options = null) { global $CFG, $DB, $OUTPUT; require_once $CFG->libdir . '/badgeslib.php'; require_once $CFG->libdir . '/completionlib.php'; require_once $CFG->libdir . '/questionlib.php'; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/group/lib.php'; require_once $CFG->dirroot . '/comment/lib.php'; require_once $CFG->dirroot . '/rating/lib.php'; require_once $CFG->dirroot . '/notes/lib.php'; // Handle course badges. badges_handle_course_deletion($courseid); // NOTE: these concatenated strings are suboptimal, but it is just extra info... $strdeleted = get_string('deleted') . ' - '; // Some crazy wishlist of stuff we should skip during purging of course content. $options = (array) $options; $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); $coursecontext = context_course::instance($courseid); $fs = get_file_storage(); // Delete course completion information, this has to be done before grades and enrols. $cc = new completion_info($course); $cc->clear_criteria(); if ($showfeedback) { echo $OUTPUT->notification($strdeleted . get_string('completion', 'completion'), 'notifysuccess'); } // Remove all data from gradebook - this needs to be done before course modules // because while deleting this information, the system may need to reference // the course modules that own the grades. remove_course_grades($courseid, $showfeedback); remove_grade_letters($coursecontext, $showfeedback); // Delete course blocks in any all child contexts, // they may depend on modules so delete them first. $childcontexts = $coursecontext->get_child_contexts(); // Returns all subcontexts since 2.2. foreach ($childcontexts as $childcontext) { blocks_delete_all_for_context($childcontext->id); } unset($childcontexts); blocks_delete_all_for_context($coursecontext->id); if ($showfeedback) { echo $OUTPUT->notification($strdeleted . get_string('type_block_plural', 'plugin'), 'notifysuccess'); } // Get the list of all modules that are properly installed. $allmodules = $DB->get_records_menu('modules', array(), '', 'name, id'); // Delete every instance of every module, // this has to be done before deleting of course level stuff. $locations = core_component::get_plugin_list('mod'); foreach ($locations as $modname => $moddir) { if ($modname === 'NEWMODULE') { continue; } if (array_key_exists($modname, $allmodules)) { $sql = "SELECT cm.*, m.id AS modinstance, m.name, '{$modname}' AS modname\n FROM {" . $modname . "} m\n LEFT JOIN {course_modules} cm ON cm.instance = m.id AND cm.module = :moduleid\n WHERE m.course = :courseid"; $instances = $DB->get_records_sql($sql, array('courseid' => $course->id, 'modulename' => $modname, 'moduleid' => $allmodules[$modname])); include_once "{$moddir}/lib.php"; // Shows php warning only if plugin defective. $moddelete = $modname . '_delete_instance'; // Delete everything connected to an instance. $moddeletecourse = $modname . '_delete_course'; // Delete other stray stuff (uncommon). if ($instances) { foreach ($instances as $cm) { if ($cm->id) { // Delete activity context questions and question categories. question_delete_activity($cm, $showfeedback); // Notify the competency subsystem. \core_competency\api::hook_course_module_deleted($cm); } if (function_exists($moddelete)) { // This purges all module data in related tables, extra user prefs, settings, etc. $moddelete($cm->modinstance); } else { // NOTE: we should not allow installation of modules with missing delete support! debugging("Defective module '{$modname}' detected when deleting course contents: missing function {$moddelete}()!"); $DB->delete_records($modname, array('id' => $cm->modinstance)); } if ($cm->id) { // Delete cm and its context - orphaned contexts are purged in cron in case of any race condition. context_helper::delete_instance(CONTEXT_MODULE, $cm->id); $DB->delete_records('course_modules', array('id' => $cm->id)); } } } if (function_exists($moddeletecourse)) { // Execute optional course cleanup callback. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6. debugging("Callback delete_course is deprecated. Function {$moddeletecourse} should be converted " . 'to observer of event \\core\\event\\course_content_deleted', DEBUG_DEVELOPER); $moddeletecourse($course, $showfeedback); } if ($instances and $showfeedback) { echo $OUTPUT->notification($strdeleted . get_string('pluginname', $modname), 'notifysuccess'); } } else { // Ooops, this module is not properly installed, force-delete it in the next block. } } // We have tried to delete everything the nice way - now let's force-delete any remaining module data. // Remove all data from availability and completion tables that is associated // with course-modules belonging to this course. Note this is done even if the // features are not enabled now, in case they were enabled previously. $DB->delete_records_select('course_modules_completion', 'coursemoduleid IN (SELECT id from {course_modules} WHERE course=?)', array($courseid)); // Remove course-module data that has not been removed in modules' _delete_instance callbacks. $cms = $DB->get_records('course_modules', array('course' => $course->id)); $allmodulesbyid = array_flip($allmodules); foreach ($cms as $cm) { if (array_key_exists($cm->module, $allmodulesbyid)) { try { $DB->delete_records($allmodulesbyid[$cm->module], array('id' => $cm->instance)); } catch (Exception $e) { // Ignore weird or missing table problems. } } context_helper::delete_instance(CONTEXT_MODULE, $cm->id); $DB->delete_records('course_modules', array('id' => $cm->id)); } if ($showfeedback) { echo $OUTPUT->notification($strdeleted . get_string('type_mod_plural', 'plugin'), 'notifysuccess'); } // Cleanup the rest of plugins. Deprecated since Moodle 3.2. TODO MDL-53297 remove in 3.6. $cleanuplugintypes = array('report', 'coursereport', 'format'); $callbacks = get_plugins_with_function('delete_course', 'lib.php'); foreach ($cleanuplugintypes as $type) { if (!empty($callbacks[$type])) { foreach ($callbacks[$type] as $pluginfunction) { debugging("Callback delete_course is deprecated. Function {$pluginfunction} should be converted " . 'to observer of event \\core\\event\\course_content_deleted', DEBUG_DEVELOPER); $pluginfunction($course->id, $showfeedback); } if ($showfeedback) { echo $OUTPUT->notification($strdeleted . get_string('type_' . $type . '_plural', 'plugin'), 'notifysuccess'); } } } // Delete questions and question categories. question_delete_course($course, $showfeedback); if ($showfeedback) { echo $OUTPUT->notification($strdeleted . get_string('questions', 'question'), 'notifysuccess'); } // Make sure there are no subcontexts left - all valid blocks and modules should be already gone. $childcontexts = $coursecontext->get_child_contexts(); // Returns all subcontexts since 2.2. foreach ($childcontexts as $childcontext) { $childcontext->delete(); } unset($childcontexts); // Remove all roles and enrolments by default. if (empty($options['keep_roles_and_enrolments'])) { // This hack is used in restore when deleting contents of existing course. role_unassign_all(array('contextid' => $coursecontext->id, 'component' => ''), true); enrol_course_delete($course); if ($showfeedback) { echo $OUTPUT->notification($strdeleted . get_string('type_enrol_plural', 'plugin'), 'notifysuccess'); } } // Delete any groups, removing members and grouping/course links first. if (empty($options['keep_groups_and_groupings'])) { groups_delete_groupings($course->id, $showfeedback); groups_delete_groups($course->id, $showfeedback); } // Filters be gone! filter_delete_all_for_context($coursecontext->id); // Notes, you shall not pass! note_delete_all($course->id); // Die comments! comment::delete_comments($coursecontext->id); // Ratings are history too. $delopt = new stdclass(); $delopt->contextid = $coursecontext->id; $rm = new rating_manager(); $rm->delete_ratings($delopt); // Delete course tags. core_tag_tag::remove_all_item_tags('core', 'course', $course->id); // Notify the competency subsystem. \core_competency\api::hook_course_deleted($course); // Delete calendar events. $DB->delete_records('event', array('courseid' => $course->id)); $fs->delete_area_files($coursecontext->id, 'calendar'); // Delete all related records in other core tables that may have a courseid // This array stores the tables that need to be cleared, as // table_name => column_name that contains the course id. $tablestoclear = array('backup_courses' => 'courseid', 'user_lastaccess' => 'courseid'); foreach ($tablestoclear as $table => $col) { $DB->delete_records($table, array($col => $course->id)); } // Delete all course backup files. $fs->delete_area_files($coursecontext->id, 'backup'); // Cleanup course record - remove links to deleted stuff. $oldcourse = new stdClass(); $oldcourse->id = $course->id; $oldcourse->summary = ''; $oldcourse->cacherev = 0; $oldcourse->legacyfiles = 0; if (!empty($options['keep_groups_and_groupings'])) { $oldcourse->defaultgroupingid = 0; } $DB->update_record('course', $oldcourse); // Delete course sections. $DB->delete_records('course_sections', array('course' => $course->id)); // Delete legacy, section and any other course files. $fs->delete_area_files($coursecontext->id, 'course'); // Files from summary and section. // Delete all remaining stuff linked to context such as files, comments, ratings, etc. if (empty($options['keep_roles_and_enrolments']) and empty($options['keep_groups_and_groupings'])) { // Easy, do not delete the context itself... $coursecontext->delete_content(); } else { // Hack alert!!!! // We can not drop all context stuff because it would bork enrolments and roles, // there might be also files used by enrol plugins... } // Delete legacy files - just in case some files are still left there after conversion to new file api, // also some non-standard unsupported plugins may try to store something there. fulldelete($CFG->dataroot . '/' . $course->id); // Delete from cache to reduce the cache size especially makes sense in case of bulk course deletion. $cachemodinfo = cache::make('core', 'coursemodinfo'); $cachemodinfo->delete($courseid); // Trigger a course content deleted event. $event = \core\event\course_content_deleted::create(array('objectid' => $course->id, 'context' => $coursecontext, 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname, 'options' => $options))); $event->add_record_snapshot('course', $course); $event->trigger(); return true; }
/** * Deletes this entry from the database. Access control checks must be done by calling code. * * @return void */ public function delete() { global $DB; $this->delete_attachments(); $this->remove_associations(); // Get record to pass onto the event. $record = $DB->get_record('post', array('id' => $this->id)); $DB->delete_records('post', array('id' => $this->id)); core_tag_tag::remove_all_item_tags('core', 'post', $this->id); $event = \core\event\blog_entry_deleted::create(array('objectid' => $this->id, 'relateduserid' => $this->userid)); $event->add_record_snapshot("post", $record); $event->set_blog_entry($this); $event->trigger(); }
/** * Update a course. * * Please note this functions does not verify any access control, * the calling code is responsible for all validation (usually it is the form definition). * * @param object $data - all the data needed for an entry in the 'course' table * @param array $editoroptions course description editor options * @return void */ function update_course($data, $editoroptions = NULL) { global $DB, $CFG; $data->timemodified = time(); $oldcourse = course_get_format($data->id)->get_course(); $context = context_course::instance($oldcourse->id); if ($editoroptions) { $data = file_postupdate_standard_editor($data, 'summary', $editoroptions, $context, 'course', 'summary', 0); } if ($overviewfilesoptions = course_overviewfiles_options($data->id)) { $data = file_postupdate_standard_filemanager($data, 'overviewfiles', $overviewfilesoptions, $context, 'course', 'overviewfiles', 0); } // Check we don't have a duplicate shortname. if (!empty($data->shortname) && $oldcourse->shortname != $data->shortname) { if ($DB->record_exists_sql('SELECT id from {course} WHERE shortname = ? AND id <> ?', array($data->shortname, $data->id))) { throw new moodle_exception('shortnametaken', '', '', $data->shortname); } } // Check we don't have a duplicate idnumber. if (!empty($data->idnumber) && $oldcourse->idnumber != $data->idnumber) { if ($DB->record_exists_sql('SELECT id from {course} WHERE idnumber = ? AND id <> ?', array($data->idnumber, $data->id))) { throw new moodle_exception('courseidnumbertaken', '', '', $data->idnumber); } } if (!isset($data->category) or empty($data->category)) { // prevent nulls and 0 in category field unset($data->category); } $changesincoursecat = $movecat = (isset($data->category) and $oldcourse->category != $data->category); if (!isset($data->visible)) { // data not from form, add missing visibility info $data->visible = $oldcourse->visible; } if ($data->visible != $oldcourse->visible) { // reset the visibleold flag when manually hiding/unhiding course $data->visibleold = $data->visible; $changesincoursecat = true; } else { if ($movecat) { $newcategory = $DB->get_record('course_categories', array('id' => $data->category)); if (empty($newcategory->visible)) { // make sure when moving into hidden category the course is hidden automatically $data->visible = 0; } } } // Update with the new data $DB->update_record('course', $data); // make sure the modinfo cache is reset rebuild_course_cache($data->id); // update course format options with full course data course_get_format($data->id)->update_course_format_options($data, $oldcourse); $course = $DB->get_record('course', array('id' => $data->id)); if ($movecat) { $newparent = context_coursecat::instance($course->category); $context->update_moved($newparent); } $fixcoursesortorder = $movecat || isset($data->sortorder) && $oldcourse->sortorder != $data->sortorder; if ($fixcoursesortorder) { fix_course_sortorder(); } // purge appropriate caches in case fix_course_sortorder() did not change anything cache_helper::purge_by_event('changesincourse'); if ($changesincoursecat) { cache_helper::purge_by_event('changesincoursecat'); } // Test for and remove blocks which aren't appropriate anymore blocks_remove_inappropriate($course); // Save any custom role names. save_local_role_names($course->id, $data); // update enrol settings enrol_course_updated(false, $course, $data); // Update course tags. if (isset($data->tags)) { core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags); } // Trigger a course updated event. $event = \core\event\course_updated::create(array('objectid' => $course->id, 'context' => context_course::instance($course->id), 'other' => array('shortname' => $course->shortname, 'fullname' => $course->fullname))); $event->set_legacy_logdata(array($course->id, 'course', 'update', 'edit.php?id=' . $course->id, $course->id)); $event->trigger(); if ($oldcourse->format !== $course->format) { // Remove all options stored for the previous format // We assume that new course format migrated everything it needed watching trigger // 'course_updated' and in method format_XXX::update_course_format_options() $DB->delete_records('course_format_options', array('courseid' => $course->id, 'format' => $oldcourse->format)); } }
/** * Test search_courses */ public function test_search_courses() { global $DB; $this->resetAfterTest(true); $this->setAdminUser(); $generatedcourses = array(); $coursedata1['fullname'] = 'FIRST COURSE'; $course1 = self::getDataGenerator()->create_course($coursedata1); $coursedata2['fullname'] = 'SECOND COURSE'; $course2 = self::getDataGenerator()->create_course($coursedata2); // Search by name. $results = core_course_external::search_courses('search', 'FIRST'); $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']); $this->assertCount(1, $results['courses']); // Create the forum. $record = new stdClass(); $record->introformat = FORMAT_HTML; $record->course = $course2->id; // Set Aggregate type = Average of ratings. $forum = self::getDataGenerator()->create_module('forum', $record); // Search by module. $results = core_course_external::search_courses('modulelist', 'forum'); $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); $this->assertEquals(1, $results['total']); // Enable coursetag option. set_config('block_tags_showcoursetags', true); // Add tag 'TAG-LABEL ON SECOND COURSE' to Course2. core_tag_tag::set_item_tags('core', 'course', $course2->id, context_course::instance($course2->id), array('TAG-LABEL ON SECOND COURSE')); $taginstance = $DB->get_record('tag_instance', array('itemtype' => 'course', 'itemid' => $course2->id), '*', MUST_EXIST); // Search by tagid. $results = core_course_external::search_courses('tagid', $taginstance->tagid); $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']); // Search by block (use news_items default block). $blockid = $DB->get_field('block', 'id', array('name' => 'news_items')); $results = core_course_external::search_courses('blocklist', $blockid); $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); $this->assertEquals(2, $results['total']); // Now as a normal user. $user = self::getDataGenerator()->create_user(); // Add a 3rd, hidden, course we shouldn't see, even when enrolled as student. $coursedata3['fullname'] = 'HIDDEN COURSE'; $coursedata3['visible'] = 0; $course3 = self::getDataGenerator()->create_course($coursedata3); $this->getDataGenerator()->enrol_user($user->id, $course3->id, 'student'); $this->getDataGenerator()->enrol_user($user->id, $course2->id, 'student'); $this->setUser($user); $results = core_course_external::search_courses('search', 'FIRST'); $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); $this->assertCount(1, $results['courses']); $this->assertEquals(1, $results['total']); $this->assertEquals($coursedata1['fullname'], $results['courses'][0]['fullname']); // Check that we can see both without the limit to enrolled setting. $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 0); $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); $this->assertCount(2, $results['courses']); $this->assertEquals(2, $results['total']); // Check that we only see our enrolled course when limiting. $results = core_course_external::search_courses('search', 'COURSE', 0, 0, array(), 1); $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results); $this->assertCount(1, $results['courses']); $this->assertEquals(1, $results['total']); $this->assertEquals($coursedata2['fullname'], $results['courses'][0]['fullname']); // Search by block (use news_items default block). Should fail (only admins allowed). $this->setExpectedException('required_capability_exception'); $results = core_course_external::search_courses('blocklist', $blockid); }
/** * Testing function core_tag_tag::combine_tags() when correlated tags are present. */ public function test_combine_tags_with_correlated() { $task = new \core\task\tag_cron_task(); $tags = $this->prepare_correlated(); $task->compute_correlations(); // Now 'cat' is correlated with 'cats'. // Also 'dog', 'dogs' and 'puppy' are correlated. // There is a manual relation between 'cat' and 'kitten'. // See function test_correlations() for assertions. // Combine tags 'dog' and 'kitten' into 'cat' and make sure that cat is now correlated with dogs and puppy. $tags['cat']->combine_tags(array($tags['dog'], $tags['kitten'])); $correlatedtags = $this->get_correlated_tags_names($tags['cat']); $this->assertEquals(['cats', 'dogs', 'puppy'], $correlatedtags); $correlatedtags = $this->get_correlated_tags_names($tags['dogs']); $this->assertEquals(['cat', 'puppy'], $correlatedtags); $correlatedtags = $this->get_correlated_tags_names($tags['puppy']); $this->assertEquals(['cat', 'dogs'], $correlatedtags); // Add tag that does not have any correlations. $user7 = $this->getDataGenerator()->create_user(); core_tag_tag::set_item_tags('core', 'user', $user7->id, context_user::instance($user7->id), array('hippo')); $tags['hippo'] = core_tag_tag::get_by_name(core_tag_collection::get_default(), 'hippo', '*'); // Combine tag 'cat' into 'hippo'. Now 'hippo' should have the same correlations 'cat' used to have and also // tags 'dogs' and 'puppy' should have 'hippo' in correlations. $tags['hippo']->combine_tags(array($tags['cat'])); $correlatedtags = $this->get_correlated_tags_names($tags['hippo']); $this->assertEquals(['cats', 'dogs', 'puppy'], $correlatedtags); $correlatedtags = $this->get_correlated_tags_names($tags['dogs']); $this->assertEquals(['hippo', 'puppy'], $correlatedtags); $correlatedtags = $this->get_correlated_tags_names($tags['puppy']); $this->assertEquals(['dogs', 'hippo'], $correlatedtags); }
$usercontext = context_user::instance($USER->id); switch ($action) { case 'addinterest': if (!core_tag_tag::is_enabled('core', 'user')) { print_error('tagdisabled'); } $tag = required_param('tag', PARAM_TAG); core_tag_tag::add_item_tag('core', 'user', $USER->id, $usercontext, $tag); $tc = core_tag_area::get_collection('core', 'user'); redirect(core_tag_tag::make_url($tc, $tag)); break; case 'removeinterest': if (!core_tag_tag::is_enabled('core', 'user')) { print_error('tagdisabled'); } $tag = required_param('tag', PARAM_TAG); core_tag_tag::remove_item_tag('core', 'user', $USER->id, $tag); $tc = core_tag_area::get_collection('core', 'user'); redirect(core_tag_tag::make_url($tc, $tag)); break; case 'flaginappropriate': require_capability('moodle/tag:flag', context_system::instance()); $id = required_param('id', PARAM_INT); $tagobject = core_tag_tag::get($id, '*', MUST_EXIST); $tagobject->flag(); redirect($tagobject->get_view_url(), get_string('responsiblewillbenotified', 'tag')); break; default: print_error('unknowaction'); break; }
/** * Private function to factor common code out of get_question_options(). * * @param object $question the question to tidy. * @param boolean $loadtags load the question tags from the tags table. Optional, default false. */ function _tidy_question($question, $loadtags = false) { global $CFG; // Load question-type specific fields. if (!question_bank::is_qtype_installed($question->qtype)) { $question->questiontext = html_writer::tag('p', get_string('warningmissingtype', 'qtype_missingtype')) . $question->questiontext; } question_bank::get_qtype($question->qtype)->get_question_options($question); // Convert numeric fields to float. (Prevents these being displayed as 1.0000000.) $question->defaultmark += 0; $question->penalty += 0; if (isset($question->_partiallyloaded)) { unset($question->_partiallyloaded); } if ($loadtags && core_tag_tag::is_enabled('core_question', 'question')) { $question->tags = core_tag_tag::get_item_tags_array('core_question', 'question', $question->id); } }
/** * Moves existing tags associated with an item type to another tag collection * * @param string $component * @param string $itemtype * @param int $tagcollid */ public static function move_tags($component, $itemtype, $tagcollid) { global $DB; $params = array('itemtype1' => $itemtype, 'component1' => $component, 'itemtype2' => $itemtype, 'component2' => $component, 'tagcollid1' => $tagcollid, 'tagcollid2' => $tagcollid); // Find all collections that need to be cleaned later. $sql = "SELECT DISTINCT t.tagcollid " . "FROM {tag_instance} ti " . "JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1 " . "WHERE ti.itemtype = :itemtype2 AND ti.component = :component2 "; $cleanupcollections = $DB->get_fieldset_sql($sql, $params); // Find all tags that are related to the tags being moved and make sure they are present in the target tagcoll. // This query is a little complicated because Oracle does not allow to run SELECT DISTINCT on CLOB fields. $sql = "SELECT name, rawname, description, descriptionformat, userid, tagtype, flag " . "FROM {tag} WHERE id IN " . "(SELECT r.id " . "FROM {tag_instance} ti " . "JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1 " . "JOIN {tag_instance} tr ON tr.itemtype = 'tag' and tr.component = 'core' AND tr.itemid = t.id " . "JOIN {tag} r ON r.id = tr.tagid " . "LEFT JOIN {tag} re ON re.name = r.name AND re.tagcollid = :tagcollid2 " . "WHERE ti.itemtype = :itemtype2 AND ti.component = :component2 " . " AND re.id IS NULL)"; // We need related tags that ARE NOT present in the target tagcoll. $result = $DB->get_records_sql($sql, $params); foreach ($result as $tag) { $tag->tagcollid = $tagcollid; $tag->id = $DB->insert_record('tag', $tag); \core\event\tag_created::create_from_tag($tag); } // Find all tags that need moving and have related tags, remember their related tags. $sql = "SELECT t.name AS tagname, r.rawname AS relatedtag " . "FROM {tag_instance} ti " . "JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1 " . "JOIN {tag_instance} tr ON t.id = tr.tagid AND tr.itemtype = 'tag' and tr.component = 'core' " . "JOIN {tag} r ON r.id = tr.itemid " . "WHERE ti.itemtype = :itemtype2 AND ti.component = :component2 " . "ORDER BY t.id, tr.ordering "; $relatedtags = array(); $result = $DB->get_recordset_sql($sql, $params); foreach ($result as $record) { $relatedtags[$record->tagname][] = $record->relatedtag; } $result->close(); // Find all tags that are used for this itemtype/component and are not present in the target tag collection. // This query is a little complicated because Oracle does not allow to run SELECT DISTINCT on CLOB fields. $sql = "SELECT id, name, rawname, description, descriptionformat, userid, tagtype, flag\n FROM {tag} WHERE id IN\n (SELECT t.id\n FROM {tag_instance} ti\n JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1\n LEFT JOIN {tag} tt ON tt.name = t.name AND tt.tagcollid = :tagcollid2\n WHERE ti.itemtype = :itemtype2 AND ti.component = :component2\n AND tt.id IS NULL)"; $movedtags = array(); // Keep track of moved tags so we don't hit DB index violation. $result = $DB->get_records_sql($sql, $params); foreach ($result as $tag) { $originaltagid = $tag->id; if (array_key_exists($tag->name, $movedtags)) { // Case of corrupted data when the same tag was in several collections. $tag->id = $movedtags[$tag->name]; } else { // Copy the tag into the new collection. unset($tag->id); $tag->tagcollid = $tagcollid; $tag->id = $DB->insert_record('tag', $tag); \core\event\tag_created::create_from_tag($tag); $movedtags[$tag->name] = $tag->id; } $DB->execute("UPDATE {tag_instance} SET tagid = ? WHERE tagid = ? AND itemtype = ? AND component = ?", array($tag->id, $originaltagid, $itemtype, $component)); } // Find all tags that are used for this itemtype/component and are already present in the target tag collection. $sql = "SELECT DISTINCT t.id, tt.id AS targettagid\n FROM {tag_instance} ti\n JOIN {tag} t ON t.id = ti.tagid AND t.tagcollid <> :tagcollid1\n JOIN {tag} tt ON tt.name = t.name AND tt.tagcollid = :tagcollid2\n WHERE ti.itemtype = :itemtype2 AND ti.component = :component2"; $result = $DB->get_records_sql($sql, $params); foreach ($result as $tag) { $DB->execute("UPDATE {tag_instance} SET tagid = ? WHERE tagid = ? AND itemtype = ? AND component = ?", array($tag->targettagid, $tag->id, $itemtype, $component)); } // Add related tags to the moved tags. if ($relatedtags) { $tags = core_tag_tag::get_by_name_bulk($tagcollid, array_keys($relatedtags)); foreach ($tags as $tag) { $tag->add_related_tags($relatedtags[$tag->name]); } } if ($cleanupcollections) { core_tag_collection::cleanup_unused_tags($cleanupcollections); } // Reset caches. cache::make('core', 'tags')->delete('tag_area'); }
/** * Returns the correlated tags of a tag, retrieved from the tag_correlation table. Make sure cron runs, otherwise the table will be * empty and this function won't return anything. * * Correlated tags are calculated in cron based on existing tag instances. * * @package core_tag * @deprecated since 3.1 * @param int $tagid is a single tag id * @param int $notused this argument is no longer used * @return array an array of tag objects or an empty if no correlated tags are found */ function tag_get_correlated($tagid, $notused = null) { debugging('Method tag_get_correlated() is deprecated, ' . 'use core_tag_tag::get_correlated_tags()', DEBUG_DEVELOPER); $result = array(); if ($tag = core_tag_tag::get($tagid)) { $tags = $tag->get_correlated_tags(true); // Convert to objects for backward-compatibility. foreach ($tags as $id => $tag) { $result[$id] = $tag->to_object(); } } return $result; }
/** * Test functions core_tag_tag::create_if_missing() and core_tag_tag::get_by_name_bulk(). */ public function test_create_get() { $tagset = array('Cat', ' Dog ', '<Mouse', '<>', 'mouse', 'Dog'); $collid = core_tag_collection::get_default(); $tags = core_tag_tag::create_if_missing($collid, $tagset); $this->assertEquals(array('cat', 'dog', 'mouse'), array_keys($tags)); $this->assertEquals('Dog', $tags['dog']->rawname); $this->assertEquals('mouse', $tags['mouse']->rawname); // Case of the last tag wins. $tags2 = core_tag_tag::create_if_missing($collid, array('CAT', 'Elephant')); $this->assertEquals(array('cat', 'elephant'), array_keys($tags2)); $this->assertEquals('Cat', $tags2['cat']->rawname); $this->assertEquals('Elephant', $tags2['elephant']->rawname); $this->assertEquals($tags['cat']->id, $tags2['cat']->id); // Tag 'cat' already existed and was not created again. $tags3 = core_tag_tag::get_by_name_bulk($collid, $tagset); $this->assertEquals(array('cat', 'dog', 'mouse'), array_keys($tags3)); $this->assertEquals('Dog', $tags3['dog']->rawname); $this->assertEquals('mouse', $tags3['mouse']->rawname); }
redirect($PAGE->url); break; case 'changetype': require_sesskey(); if ($tagid && $tagobject->update(array('isstandard' => $isstandard ? 1 : 0))) { redirect(new moodle_url($PAGE->url, array('notice' => 'typechanged'))); } redirect($PAGE->url); break; case 'addstandardtag': require_sesskey(); $tagobjects = null; if ($tagcoll) { $otagsadd = optional_param('otagsadd', '', PARAM_RAW); $newtags = preg_split('/\\s*,\\s*/', trim($otagsadd), -1, PREG_SPLIT_NO_EMPTY); $tagobjects = core_tag_tag::create_if_missing($tagcoll->id, $newtags, true); } foreach ($tagobjects as $tagobject) { if (!$tagobject->isstandard) { $tagobject->update(array('isstandard' => 1)); } } redirect(new moodle_url($PAGE->url, $tagobjects ? array('notice' => 'added') : null)); break; } echo $OUTPUT->header(); if ($notice && get_string_manager()->string_exists($notice, 'tag')) { echo $OUTPUT->notification(get_string($notice, 'tag'), 'notifysuccess'); } if (!$tagcoll) { // Tag collection is not specified. Display the overview of tag collections and tag areas.
/** * Powerful function that is used by edit and editadvanced to add common form elements/rules/etc. * * @param moodleform $mform * @param array $editoroptions * @param array $filemanageroptions * @param stdClass $user */ function useredit_shared_definition(&$mform, $editoroptions, $filemanageroptions, $user) { global $CFG, $USER, $DB; if ($user->id > 0) { useredit_load_preferences($user, false); } $strrequired = get_string('required'); $stringman = get_string_manager(); // Add the necessary names. foreach (useredit_get_required_name_fields() as $fullname) { $mform->addElement('text', $fullname, get_string($fullname), 'maxlength="100" size="30"'); if ($stringman->string_exists('missing' . $fullname, 'core')) { $strmissingfield = get_string('missing' . $fullname, 'core'); } else { $strmissingfield = $strrequired; } $mform->addRule($fullname, $strmissingfield, 'required', null, 'client'); $mform->setType($fullname, PARAM_NOTAGS); } $enabledusernamefields = useredit_get_enabled_name_fields(); // Add the enabled additional name fields. foreach ($enabledusernamefields as $addname) { $mform->addElement('text', $addname, get_string($addname), 'maxlength="100" size="30"'); $mform->setType($addname, PARAM_NOTAGS); } // Do not show email field if change confirmation is pending. if ($user->id > 0 and !empty($CFG->emailchangeconfirmation) and !empty($user->preference_newemail)) { $notice = get_string('emailchangepending', 'auth', $user); $notice .= '<br /><a href="edit.php?cancelemailchange=1&id=' . $user->id . '">' . get_string('emailchangecancel', 'auth') . '</a>'; $mform->addElement('static', 'emailpending', get_string('email'), $notice); } else { $mform->addElement('text', 'email', get_string('email'), 'maxlength="100" size="30"'); $mform->addRule('email', $strrequired, 'required', null, 'client'); $mform->setType('email', PARAM_RAW_TRIMMED); } $choices = array(); $choices['0'] = get_string('emaildisplayno'); $choices['1'] = get_string('emaildisplayyes'); $choices['2'] = get_string('emaildisplaycourse'); $mform->addElement('select', 'maildisplay', get_string('emaildisplay'), $choices); $mform->setDefault('maildisplay', core_user::get_property_default('maildisplay')); $mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="21"'); $mform->setType('city', PARAM_TEXT); if (!empty($CFG->defaultcity)) { $mform->setDefault('city', $CFG->defaultcity); } $choices = get_string_manager()->get_list_of_countries(); $choices = array('' => get_string('selectacountry') . '...') + $choices; $mform->addElement('select', 'country', get_string('selectacountry'), $choices); if (!empty($CFG->country)) { $mform->setDefault('country', core_user::get_property_default('country')); } if (isset($CFG->forcetimezone) and $CFG->forcetimezone != 99) { $choices = core_date::get_list_of_timezones($CFG->forcetimezone); $mform->addElement('static', 'forcedtimezone', get_string('timezone'), $choices[$CFG->forcetimezone]); $mform->addElement('hidden', 'timezone'); $mform->setType('timezone', core_user::get_property_type('timezone')); } else { $choices = core_date::get_list_of_timezones($user->timezone, true); $mform->addElement('select', 'timezone', get_string('timezone'), $choices); } if (!empty($CFG->allowuserthemes)) { $choices = array(); $choices[''] = get_string('default'); $themes = get_list_of_themes(); foreach ($themes as $key => $theme) { if (empty($theme->hidefromselector)) { $choices[$key] = get_string('pluginname', 'theme_' . $theme->name); } } $mform->addElement('select', 'theme', get_string('preferredtheme'), $choices); } $mform->addElement('editor', 'description_editor', get_string('userdescription'), null, $editoroptions); $mform->setType('description_editor', PARAM_CLEANHTML); $mform->addHelpButton('description_editor', 'userdescription'); if (empty($USER->newadminuser)) { $mform->addElement('header', 'moodle_picture', get_string('pictureofuser')); $mform->setExpanded('moodle_picture', true); if (!empty($CFG->enablegravatar)) { $mform->addElement('html', html_writer::tag('p', get_string('gravatarenabled'))); } $mform->addElement('static', 'currentpicture', get_string('currentpicture')); $mform->addElement('checkbox', 'deletepicture', get_string('delete')); $mform->setDefault('deletepicture', 0); $mform->addElement('filemanager', 'imagefile', get_string('newpicture'), '', $filemanageroptions); $mform->addHelpButton('imagefile', 'newpicture'); $mform->addElement('text', 'imagealt', get_string('imagealt'), 'maxlength="100" size="30"'); $mform->setType('imagealt', PARAM_TEXT); } // Display user name fields that are not currenlty enabled here if there are any. $disabledusernamefields = useredit_get_disabled_name_fields($enabledusernamefields); if (count($disabledusernamefields) > 0) { $mform->addElement('header', 'moodle_additional_names', get_string('additionalnames')); foreach ($disabledusernamefields as $allname) { $mform->addElement('text', $allname, get_string($allname), 'maxlength="100" size="30"'); $mform->setType($allname, PARAM_NOTAGS); } } if (core_tag_tag::is_enabled('core', 'user') and empty($USER->newadminuser)) { $mform->addElement('header', 'moodle_interests', get_string('interests')); $mform->addElement('tags', 'interests', get_string('interestslist'), array('itemtype' => 'user', 'component' => 'core')); $mform->addHelpButton('interests', 'interestslist'); } // Moodle optional fields. $mform->addElement('header', 'moodle_optional', get_string('optional', 'form')); $mform->addElement('text', 'url', get_string('webpage'), 'maxlength="255" size="50"'); $mform->setType('url', core_user::get_property_type('url')); $mform->addElement('text', 'icq', get_string('icqnumber'), 'maxlength="15" size="25"'); $mform->setType('icq', core_user::get_property_type('icq')); $mform->setForceLtr('icq'); $mform->addElement('text', 'skype', get_string('skypeid'), 'maxlength="50" size="25"'); $mform->setType('skype', core_user::get_property_type('skype')); $mform->setForceLtr('skype'); $mform->addElement('text', 'aim', get_string('aimid'), 'maxlength="50" size="25"'); $mform->setType('aim', core_user::get_property_type('aim')); $mform->setForceLtr('aim'); $mform->addElement('text', 'yahoo', get_string('yahooid'), 'maxlength="50" size="25"'); $mform->setType('yahoo', core_user::get_property_type('yahoo')); $mform->setForceLtr('yahoo'); $mform->addElement('text', 'msn', get_string('msnid'), 'maxlength="50" size="25"'); $mform->setType('msn', core_user::get_property_type('msn')); $mform->setForceLtr('msn'); $mform->addElement('text', 'idnumber', get_string('idnumber'), 'maxlength="255" size="25"'); $mform->setType('idnumber', core_user::get_property_type('idnumber')); $mform->addElement('text', 'institution', get_string('institution'), 'maxlength="255" size="25"'); $mform->setType('institution', core_user::get_property_type('institution')); $mform->addElement('text', 'department', get_string('department'), 'maxlength="255" size="25"'); $mform->setType('department', core_user::get_property_type('department')); $mform->addElement('text', 'phone1', get_string('phone1'), 'maxlength="20" size="25"'); $mform->setType('phone1', core_user::get_property_type('phone1')); $mform->setForceLtr('phone1'); $mform->addElement('text', 'phone2', get_string('phone2'), 'maxlength="20" size="25"'); $mform->setType('phone2', core_user::get_property_type('phone2')); $mform->setForceLtr('phone2'); $mform->addElement('text', 'address', get_string('address'), 'maxlength="255" size="25"'); $mform->setType('address', core_user::get_property_type('address')); }
protected function process_tag($data) { global $CFG, $DB; $data = (object) $data; $newquestion = $this->get_new_parentid('question'); $questioncreated = (bool) $this->get_mappingid('question_created', $this->get_old_parentid('question')); if (!$questioncreated) { // This question already exists in the question bank. Nothing for us to do. return; } if (core_tag_tag::is_enabled('core_question', 'question')) { $tagname = $data->rawname; // Get the category, so we can then later get the context. $categoryid = $this->get_new_parentid('question_category'); if (empty($this->cachedcategory) || $this->cachedcategory->id != $categoryid) { $this->cachedcategory = $DB->get_record('question_categories', array('id' => $categoryid)); } // Add the tag to the question. core_tag_tag::add_item_tag('core_question', 'question', $newquestion, context::instance_by_id($this->cachedcategory->contextid), $tagname); } }
$entry->courseassoc = $assocrec->contextid; break; case CONTEXT_MODULE: $entry->modassoc = $assocrec->contextid; break; } } } } $summaryoptions = array('maxfiles' => 99, 'maxbytes' => $CFG->maxbytes, 'trusttext' => true, 'context' => $sitecontext, 'subdirs' => file_area_contains_subdirs($sitecontext, 'blog', 'post', $entry->id)); $attachmentoptions = array('subdirs' => false, 'maxfiles' => 99, 'maxbytes' => $CFG->maxbytes); $blogeditform = new blog_edit_form(null, compact('entry', 'summaryoptions', 'attachmentoptions', 'sitecontext', 'courseid', 'modid')); $entry = file_prepare_standard_editor($entry, 'summary', $summaryoptions, $sitecontext, 'blog', 'post', $entry->id); $entry = file_prepare_standard_filemanager($entry, 'attachment', $attachmentoptions, $sitecontext, 'blog', 'attachment', $entry->id); if (!empty($entry->id)) { $entry->tags = core_tag_tag::get_item_tags_array('core', 'post', $entry->id); } $entry->action = $action; // Set defaults. $blogeditform->set_data($entry); if ($blogeditform->is_cancelled()) { redirect($returnurl); } else { if ($data = $blogeditform->get_data()) { switch ($action) { case 'add': $blogentry = new blog_entry(null, $data, $blogeditform); $blogentry->add(); $blogentry->edit($data, $blogeditform, $summaryoptions, $attachmentoptions); break; case 'edit':
/** * Get tags by their ids * * @param array $params */ public static function get_tagindex($params) { global $PAGE; // Validate and normalize parameters. $tagindex = self::validate_parameters(self::get_tagindex_parameters(), array('tagindex' => $params)); $params = $tagindex['tagindex'] + array('excl' => 0, 'from' => 0, 'ctx' => 0, 'rec' => 1, 'page' => 0); // Login to the course / module if applicable. $context = $params['ctx'] ? context::instance_by_id($params['ctx']) : context_system::instance(); require_login(null, false, null, false, true); self::validate_context($context); $tag = core_tag_tag::get_by_name($params['tc'], $params['tag'], '*', MUST_EXIST); $tagareas = core_tag_collection::get_areas($params['tc']); $tagindex = $tag->get_tag_index($tagareas[$params['ta']], $params['excl'], $params['from'], $params['ctx'], $params['rec'], $params['page']); $renderer = $PAGE->get_renderer('core'); return $tagindex->export_for_template($renderer); }
/** * Generate any blog RSS feed via one function * * @param stdClass $context The context of the blog for which the feed it being generated * @param array $args An array of arguements needed to build the feed (contextid, token, componentname, type, id, tagid) */ function blog_rss_get_feed($context, $args) { global $CFG, $SITE, $DB; if (empty($CFG->enableblogs)) { debugging('Blogging disabled on this site, RSS feeds are not available'); return null; } if (empty($CFG->enablerssfeeds)) { debugging('Sorry, RSS feeds are disabled on this site'); return ''; } if ($CFG->bloglevel == BLOG_SITE_LEVEL) { if (isguestuser()) { debugging(get_string('nopermissiontoshow', 'error')); return ''; } } $sitecontext = context_system::instance(); if (!has_capability('moodle/blog:view', $sitecontext)) { return null; } $type = clean_param($args[3], PARAM_ALPHA); $id = clean_param($args[4], PARAM_INT); // Could be groupid / courseid / userid depending on $type. $tagid = 0; if ($args[5] != 'rss.xml') { $tagid = clean_param($args[5], PARAM_INT); } else { $tagid = 0; } $filename = blog_rss_file_name($type, $id, $tagid); if (file_exists($filename)) { if (filemtime($filename) + 3600 > time()) { return $filename; // It's already done so we return cached version. } } $courseid = $groupid = $userid = null; switch ($type) { case 'site': break; case 'course': $courseid = $id; break; case 'group': $groupid = $id; break; case 'user': $userid = $id; break; } // Get all the entries from the database. require_once $CFG->dirroot . '/blog/locallib.php'; $blogheaders = blog_get_headers($courseid, $groupid, $userid, $tagid); $bloglisting = new blog_listing($blogheaders['filters']); $blogentries = $bloglisting->get_entries(); // Now generate an array of RSS items. if ($blogentries) { $items = array(); foreach ($blogentries as $blogentry) { $item = new stdClass(); $item->author = fullname($DB->get_record('user', array('id' => $blogentry->userid))); // TODO: this is slow. $item->title = $blogentry->subject; $item->pubdate = $blogentry->lastmodified; $item->link = $CFG->wwwroot . '/blog/index.php?entryid=' . $blogentry->id; $summary = file_rewrite_pluginfile_urls($blogentry->summary, 'pluginfile.php', $sitecontext->id, 'blog', 'post', $blogentry->id); $item->description = format_text($summary, $blogentry->format); if ($blogtags = core_tag_tag::get_item_tags_array('core', 'post', $blogentry->id)) { $item->tags = $blogtags; $item->tagscheme = $CFG->wwwroot . '/tag'; } $items[] = $item; } $articles = rss_add_items($items); // Change structure to XML. } else { $articles = ''; } // Get header and footer information. switch ($type) { case 'user': $info = fullname($DB->get_record('user', array('id' => $id), get_all_user_name_fields(true))); break; case 'course': $info = $DB->get_field('course', 'fullname', array('id' => $id)); $info = format_string($info, true, array('context' => context_course::instance($id))); break; case 'site': $info = format_string($SITE->fullname, true, array('context' => context_course::instance(SITEID))); break; case 'group': $group = groups_get_group($id); $info = $group->name; // TODO: $DB->get_field('groups', 'name', array('id' => $id)). break; default: $info = ''; break; } if ($tagid) { $info .= ': ' . $DB->get_field('tags', 'text', array('id' => $tagid)); } $header = rss_standard_header(get_string($type . 'blog', 'blog', $info), $CFG->wwwroot . '/blog/index.php', get_string('intro', 'blog')); $footer = rss_standard_footer(); // Save the XML contents to file. $rssdata = $header . $articles . $footer; if (blog_rss_save_file($type, $id, $tagid, $rssdata)) { return $filename; } else { return false; // Couldn't find it or make it. } }
/** * Permanently deletes all non-standard tags that no longer have any instances pointing to them * * @param array $collections optional list of tag collections ids to cleanup */ public static function cleanup_unused_tags($collections = null) { global $DB, $CFG; $params = array(); $sql = "SELECT tg.id FROM {tag} tg LEFT OUTER JOIN {tag_instance} ti ON ti.tagid = tg.id\n WHERE ti.id IS NULL AND tg.isstandard = 0"; if ($collections) { list($sqlcoll, $params) = $DB->get_in_or_equal($collections, SQL_PARAMS_NAMED); $sql .= " AND tg.tagcollid " . $sqlcoll; } if ($unusedtags = $DB->get_fieldset_sql($sql, $params)) { core_tag_tag::delete_tags($unusedtags); } }
protected function print_save() { global $CFG, $USER, $OUTPUT, $PAGE; $url = $CFG->wwwroot . '/mod/wiki/edit.php?pageid=' . $this->page->id; if (!empty($this->section)) { $url .= "§ion=" . urlencode($this->section); } $params = array('attachmentoptions' => page_wiki_edit::$attachmentoptions, 'format' => $this->format, 'version' => $this->versionnumber, 'contextid' => $this->modcontext->id); if ($this->format != 'html') { $params['fileitemid'] = $this->page->id; $params['component'] = 'mod_wiki'; $params['filearea'] = 'attachments'; } $form = new mod_wiki_edit_form($url, $params); $save = false; $data = false; if ($data = $form->get_data()) { if ($this->format == 'html') { $data = file_postupdate_standard_editor($data, 'newcontent', page_wiki_edit::$attachmentoptions, $this->modcontext, 'mod_wiki', 'attachments', $this->subwiki->id); } if (isset($this->section)) { $save = wiki_save_section($this->page, $this->section, $data->newcontent, $USER->id); } else { $save = wiki_save_page($this->page, $data->newcontent, $USER->id); } } if ($save && $data) { core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $this->page->id, $this->modcontext, $data->tags); $message = '<p>' . get_string('saving', 'wiki') . '</p>'; if (!empty($save['sections'])) { foreach ($save['sections'] as $s) { $message .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>'; } } if ($this->versionnumber + 1 != $save['version']) { $message .= '<p>' . get_string('wrongversionsave', 'wiki') . '</p>'; } if (isset($errors) && !empty($errors)) { foreach ($errors as $e) { $message .= "<p>" . get_string('filenotuploadederror', 'wiki', $e->get_filename()) . "</p>"; } } //deleting old locks wiki_delete_locks($this->page->id, $USER->id, $this->section); $url = new moodle_url('/mod/wiki/view.php', array('pageid' => $this->page->id, 'group' => $this->subwiki->groupid)); redirect($url); } else { print_error('savingerror', 'wiki'); } }
/** * Testing function course_get_tagged_course_modules - search tagged course modules */ public function test_course_get_tagged_course_modules() { global $DB; $this->resetAfterTest(); $course3 = $this->getDataGenerator()->create_course(); $course2 = $this->getDataGenerator()->create_course(); $course1 = $this->getDataGenerator()->create_course(); $cm11 = $this->getDataGenerator()->create_module('assign', array('course' => $course1->id, 'tags' => 'Cat, Dog')); $cm12 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse', 'visible' => 0)); $cm13 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse, Dog')); $cm21 = $this->getDataGenerator()->create_module('forum', array('course' => $course2->id, 'tags' => 'Cat, Mouse')); $cm31 = $this->getDataGenerator()->create_module('forum', array('course' => $course3->id, 'tags' => 'Cat, Mouse')); // Admin is able to view everything. $this->setAdminUser(); $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, 0, 1, 0); $this->assertRegExp('/' . $cm11->name . '/', $res->content); $this->assertRegExp('/' . $cm12->name . '/', $res->content); $this->assertRegExp('/' . $cm13->name . '/', $res->content); $this->assertRegExp('/' . $cm21->name . '/', $res->content); $this->assertRegExp('/' . $cm31->name . '/', $res->content); // Results from course1 are returned before results from course2. $this->assertTrue(strpos($res->content, $cm11->name) < strpos($res->content, $cm21->name)); // Ordinary user is not able to see anything. $user = $this->getDataGenerator()->create_user(); $this->setUser($user); $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, 0, 1, 0); $this->assertNull($res); // Enrol user as student in course1 and course2. $roleids = $DB->get_records_menu('role', null, '', 'shortname, id'); $this->getDataGenerator()->enrol_user($user->id, $course1->id, $roleids['student']); $this->getDataGenerator()->enrol_user($user->id, $course2->id, $roleids['student']); core_tag_index_builder::reset_caches(); // Searching in the course context returns visible modules in this course. $context = context_course::instance($course1->id); $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, $context->id, 1, 0); $this->assertRegExp('/' . $cm11->name . '/', $res->content); $this->assertNotRegExp('/' . $cm12->name . '/', $res->content); $this->assertRegExp('/' . $cm13->name . '/', $res->content); $this->assertNotRegExp('/' . $cm21->name . '/', $res->content); $this->assertNotRegExp('/' . $cm31->name . '/', $res->content); // Searching FROM the course context returns visible modules in all courses. $context = context_course::instance($course2->id); $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, $context->id, 0, 1, 0); $this->assertRegExp('/' . $cm11->name . '/', $res->content); $this->assertNotRegExp('/' . $cm12->name . '/', $res->content); $this->assertRegExp('/' . $cm13->name . '/', $res->content); $this->assertRegExp('/' . $cm21->name . '/', $res->content); $this->assertNotRegExp('/' . $cm31->name . '/', $res->content); // No access to course3. // Results from course2 are returned before results from course1. $this->assertTrue(strpos($res->content, $cm21->name) < strpos($res->content, $cm11->name)); // Enrol user in course1 as a teacher - now he should be able to see hidden module. $this->getDataGenerator()->enrol_user($user->id, $course1->id, $roleids['editingteacher']); get_fast_modinfo(0, 0, true); $context = context_course::instance($course1->id); $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, $context->id, 0, 1, 0); $this->assertRegExp('/' . $cm12->name . '/', $res->content); // Create more modules and try pagination. $cm14 = $this->getDataGenerator()->create_module('assign', array('course' => $course1->id, 'tags' => 'Cat, Dog')); $cm15 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse', 'visible' => 0)); $cm16 = $this->getDataGenerator()->create_module('page', array('course' => $course1->id, 'tags' => 'Cat, Mouse, Dog')); $context = context_course::instance($course1->id); $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, $context->id, 1, 0); $this->assertRegExp('/' . $cm11->name . '/', $res->content); $this->assertRegExp('/' . $cm12->name . '/', $res->content); $this->assertRegExp('/' . $cm13->name . '/', $res->content); $this->assertNotRegExp('/' . $cm21->name . '/', $res->content); $this->assertRegExp('/' . $cm14->name . '/', $res->content); $this->assertRegExp('/' . $cm15->name . '/', $res->content); $this->assertNotRegExp('/' . $cm16->name . '/', $res->content); $this->assertNotRegExp('/' . $cm31->name . '/', $res->content); // No access to course3. $this->assertEmpty($res->prevpageurl); $this->assertNotEmpty($res->nextpageurl); $res = course_get_tagged_course_modules(core_tag_tag::get_by_name(0, 'Cat'), false, 0, $context->id, 1, 1); $this->assertNotRegExp('/' . $cm11->name . '/', $res->content); $this->assertNotRegExp('/' . $cm12->name . '/', $res->content); $this->assertNotRegExp('/' . $cm13->name . '/', $res->content); $this->assertNotRegExp('/' . $cm21->name . '/', $res->content); $this->assertNotRegExp('/' . $cm14->name . '/', $res->content); $this->assertNotRegExp('/' . $cm15->name . '/', $res->content); $this->assertRegExp('/' . $cm16->name . '/', $res->content); $this->assertNotRegExp('/' . $cm31->name . '/', $res->content); // No access to course3. $this->assertNotEmpty($res->prevpageurl); $this->assertEmpty($res->nextpageurl); }
/** * This function tests that the functions responsible for moving questions to * different contexts also updates the tag instances associated with the questions. */ public function test_altering_tag_instance_context() { global $CFG, $DB; // Set to admin user. $this->setAdminUser(); // Create two course categories - we are going to delete one of these later and will expect // all the questions belonging to the course in the deleted category to be moved. $coursecat1 = $this->getDataGenerator()->create_category(); $coursecat2 = $this->getDataGenerator()->create_category(); // Create a couple of categories and questions. $context1 = context_coursecat::instance($coursecat1->id); $context2 = context_coursecat::instance($coursecat2->id); $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $questioncat1 = $questiongenerator->create_question_category(array('contextid' => $context1->id)); $questioncat2 = $questiongenerator->create_question_category(array('contextid' => $context2->id)); $question1 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat1->id)); $question2 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat1->id)); $question3 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat2->id)); $question4 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat2->id)); // Now lets tag these questions. core_tag_tag::set_item_tags('core_question', 'question', $question1->id, $context1, array('tag 1', 'tag 2')); core_tag_tag::set_item_tags('core_question', 'question', $question2->id, $context1, array('tag 3', 'tag 4')); core_tag_tag::set_item_tags('core_question', 'question', $question3->id, $context2, array('tag 5', 'tag 6')); core_tag_tag::set_item_tags('core_question', 'question', $question4->id, $context2, array('tag 7', 'tag 8')); // Test moving the questions to another category. question_move_questions_to_category(array($question1->id, $question2->id), $questioncat2->id); // Test that all tag_instances belong to one context. $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Test moving them back. question_move_questions_to_category(array($question1->id, $question2->id), $questioncat1->id); // Test that all tag_instances are now reset to how they were initially. $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat1->contextid))); $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Now test moving a whole question category to another context. question_move_category_to_context($questioncat1->id, $questioncat1->contextid, $questioncat2->contextid); // Test that all tag_instances belong to one context. $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Now test moving them back. question_move_category_to_context($questioncat1->id, $questioncat2->contextid, context_coursecat::instance($coursecat1->id)->id); // Test that all tag_instances are now reset to how they were initially. $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat1->contextid))); $this->assertEquals(4, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Now we want to test deleting the course category and moving the questions to another category. question_delete_course_category($coursecat1, $coursecat2, false); // Test that all tag_instances belong to one context. $this->assertEquals(8, $DB->count_records('tag_instance', array('component' => 'core_question', 'contextid' => $questioncat2->contextid))); // Create a course. $course = $this->getDataGenerator()->create_course(); // Create some question categories and questions in this course. $coursecontext = context_course::instance($course->id); $questioncat = $questiongenerator->create_question_category(array('contextid' => $coursecontext->id)); $question1 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat->id)); $question2 = $questiongenerator->create_question('shortanswer', null, array('category' => $questioncat->id)); // Add some tags to these questions. core_tag_tag::set_item_tags('core_question', 'question', $question1->id, $coursecontext, array('tag 1', 'tag 2')); core_tag_tag::set_item_tags('core_question', 'question', $question2->id, $coursecontext, array('tag 1', 'tag 2')); // Create a course that we are going to restore the other course to. $course2 = $this->getDataGenerator()->create_course(); // Create backup file and save it to the backup location. $bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2); $bc->execute_plan(); $results = $bc->get_results(); $file = $results['backup_destination']; $fp = get_file_packer('application/vnd.moodle.backup'); $filepath = $CFG->dataroot . '/temp/backup/test-restore-course'; $file->extract_to_pathname($fp, $filepath); $bc->destroy(); // Now restore the course. $rc = new restore_controller('test-restore-course', $course2->id, backup::INTERACTIVE_NO, backup::MODE_GENERAL, 2, backup::TARGET_NEW_COURSE); $rc->execute_precheck(); $rc->execute_plan(); // Get the created question category. $restoredcategory = $DB->get_record('question_categories', array('contextid' => context_course::instance($course2->id)->id), '*', MUST_EXIST); // Check that there are two questions in the restored to course's context. $this->assertEquals(2, $DB->count_records('question', array('category' => $restoredcategory->id))); $rc->destroy(); }
function wiki_print_page_content($page, $context, $subwikiid) { global $OUTPUT, $CFG; if ($page->timerendered + WIKI_REFRESH_CACHE_TIME < time()) { $content = wiki_refresh_cachedcontent($page); $page = $content['page']; } if (isset($content)) { $box = ''; foreach ($content['sections'] as $s) { $box .= '<p>' . get_string('repeatedsection', 'wiki', $s) . '</p>'; } if (!empty($box)) { echo $OUTPUT->box($box); } } $html = file_rewrite_pluginfile_urls($page->cachedcontent, 'pluginfile.php', $context->id, 'mod_wiki', 'attachments', $subwikiid); $html = format_text($html, FORMAT_MOODLE, array('overflowdiv' => true, 'allowid' => true)); echo $OUTPUT->box($html); echo $OUTPUT->tag_list(core_tag_tag::get_item_tags('mod_wiki', 'wiki_pages', $page->id), null, 'wiki-tags'); wiki_increment_pageviews($page); }
} } // Guest can not edit. if (isguestuser()) { print_error('guestnoeditprofile'); } // The user profile we are editing. if (!($user = $DB->get_record('user', array('id' => $userid)))) { print_error('invaliduserid'); } // Guest can not be edited. if (isguestuser($user)) { print_error('guestnoeditprofile'); } // User interests separated by commas. $user->interests = core_tag_tag::get_item_tags_array('core', 'user', $user->id); // Remote users cannot be edited. We have to perform the strict // user_not_fully_set_up() check, otherwise the remote user could end up in // endless loop between user/view.php and herein. Note that required custom // fields are not supported in MNet environment anyway. if (is_mnet_remote_user($user)) { if (user_not_fully_set_up($user, true)) { $hostwwwroot = $DB->get_field('mnet_host', 'wwwroot', array('id' => $user->mnethostid)); print_error('usernotfullysetup', 'mnet', '', $hostwwwroot); } redirect($CFG->wwwroot . "/user/view.php?course={$course->id}"); } // Load the appropriate auth plugin. $userauth = get_auth_plugin($user->auth); if (!$userauth->can_edit_profile()) { print_error('noprofileedit', 'auth');
/** * Handle showing/processing the submission from the block editing form. * @return boolean true if the form was submitted and the new config saved. Does not * return if the editing form was displayed. False otherwise. */ public function process_url_edit() { global $CFG, $DB, $PAGE, $OUTPUT; $blockid = optional_param('bui_editid', null, PARAM_INT); if (!$blockid) { return false; } require_sesskey(); require_once $CFG->dirroot . '/blocks/edit_form.php'; $block = $this->find_instance($blockid); if (!$block->user_can_edit() && !$this->page->user_can_edit_blocks()) { throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock')); } $editpage = new moodle_page(); $editpage->set_pagelayout('admin'); $editpage->set_course($this->page->course); //$editpage->set_context($block->context); $editpage->set_context($this->page->context); if ($this->page->cm) { $editpage->set_cm($this->page->cm); } $editurlbase = str_replace($CFG->wwwroot . '/', '/', $this->page->url->out_omit_querystring()); $editurlparams = $this->page->url->params(); $editurlparams['bui_editid'] = $blockid; $editpage->set_url($editurlbase, $editurlparams); $editpage->set_block_actions_done(); // At this point we are either going to redirect, or display the form, so // overwrite global $PAGE ready for this. (Formslib refers to it.) $PAGE = $editpage; //some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that to $output = $editpage->get_renderer('core'); $OUTPUT = $output; $formfile = $CFG->dirroot . '/blocks/' . $block->name() . '/edit_form.php'; if (is_readable($formfile)) { require_once $formfile; $classname = 'block_' . $block->name() . '_edit_form'; if (!class_exists($classname)) { $classname = 'block_edit_form'; } } else { $classname = 'block_edit_form'; } $mform = new $classname($editpage->url, $block, $this->page); $mform->set_data($block->instance); if ($mform->is_cancelled()) { redirect($this->page->url); } else { if ($data = $mform->get_data()) { $bi = new stdClass(); $bi->id = $block->instance->id; // This may get overwritten by the special case handling below. $bi->pagetypepattern = $data->bui_pagetypepattern; $bi->showinsubcontexts = (bool) $data->bui_contexts; if (empty($data->bui_subpagepattern) || $data->bui_subpagepattern == '%@NULL@%') { $bi->subpagepattern = null; } else { $bi->subpagepattern = $data->bui_subpagepattern; } $systemcontext = context_system::instance(); $frontpagecontext = context_course::instance(SITEID); $parentcontext = context::instance_by_id($data->bui_parentcontextid); // Updating stickiness and contexts. See MDL-21375 for details. if (has_capability('moodle/site:manageblocks', $parentcontext)) { // Check permissions in destination // Explicitly set the default context $bi->parentcontextid = $parentcontext->id; if ($data->bui_editingatfrontpage) { // The block is being edited on the front page // The interface here is a special case because the pagetype pattern is // totally derived from the context menu. Here are the excpetions. MDL-30340 switch ($data->bui_contexts) { case BUI_CONTEXTS_ENTIRE_SITE: // The user wants to show the block across the entire site $bi->parentcontextid = $systemcontext->id; $bi->showinsubcontexts = true; $bi->pagetypepattern = '*'; break; case BUI_CONTEXTS_FRONTPAGE_SUBS: // The user wants the block shown on the front page and all subcontexts $bi->parentcontextid = $frontpagecontext->id; $bi->showinsubcontexts = true; $bi->pagetypepattern = '*'; break; case BUI_CONTEXTS_FRONTPAGE_ONLY: // The user want to show the front page on the frontpage only $bi->parentcontextid = $frontpagecontext->id; $bi->showinsubcontexts = false; $bi->pagetypepattern = 'site-index'; // This is the only relevant page type anyway but we'll set it explicitly just // in case the front page grows site-index-* subpages of its own later break; } } } $bits = explode('-', $bi->pagetypepattern); // hacks for some contexts if ($parentcontext->contextlevel == CONTEXT_COURSE && $parentcontext->instanceid != SITEID) { // For course context // is page type pattern is mod-*, change showinsubcontext to 1 if ($bits[0] == 'mod' || $bi->pagetypepattern == '*') { $bi->showinsubcontexts = 1; } else { $bi->showinsubcontexts = 0; } } else { if ($parentcontext->contextlevel == CONTEXT_USER) { // for user context // subpagepattern should be null if ($bits[0] == 'user' or $bits[0] == 'my') { // we don't need subpagepattern in usercontext $bi->subpagepattern = null; } } } $bi->defaultregion = $data->bui_defaultregion; $bi->defaultweight = $data->bui_defaultweight; $DB->update_record('block_instances', $bi); if (!empty($block->config)) { $config = clone $block->config; } else { $config = new stdClass(); } foreach ($data as $configfield => $value) { if (strpos($configfield, 'config_') !== 0) { continue; } $field = substr($configfield, 7); $config->{$field} = $value; } $block->instance_config_save($config); $bp = new stdClass(); $bp->visible = $data->bui_visible; $bp->region = $data->bui_region; $bp->weight = $data->bui_weight; $needbprecord = !$data->bui_visible || $data->bui_region != $data->bui_defaultregion || $data->bui_weight != $data->bui_defaultweight; if ($block->instance->blockpositionid && !$needbprecord) { $DB->delete_records('block_positions', array('id' => $block->instance->blockpositionid)); } else { if ($block->instance->blockpositionid && $needbprecord) { $bp->id = $block->instance->blockpositionid; $DB->update_record('block_positions', $bp); } else { if ($needbprecord) { $bp->blockinstanceid = $block->instance->id; $bp->contextid = $this->page->context->id; $bp->pagetype = $this->page->pagetype; if ($this->page->subpage) { $bp->subpage = $this->page->subpage; } else { $bp->subpage = ''; } $DB->insert_record('block_positions', $bp); } } } redirect($this->page->url); } else { $strheading = get_string('blockconfiga', 'moodle', $block->get_title()); $editpage->set_title($strheading); $editpage->set_heading($strheading); $bits = explode('-', $this->page->pagetype); if ($bits[0] == 'tag' && !empty($this->page->subpage)) { // better navbar for tag pages $editpage->navbar->add(get_string('tags'), new moodle_url('/tag/')); $tag = core_tag_tag::get($this->page->subpage); // tag search page doesn't have subpageid if ($tag) { $editpage->navbar->add($tag->get_display_name(), $tag->get_view_url()); } } $editpage->navbar->add($block->get_title()); $editpage->navbar->add(get_string('configuration')); echo $output->header(); echo $output->heading($strheading, 2); $mform->display(); echo $output->footer(); exit; } } }