/** * Constructor * * @param string|moodle_url $pageurl */ public function __construct($pageurl) { global $OUTPUT; parent::__construct(); $this->attributes['class'] = 'generaltable tag-areas-table'; $this->head = array(get_string('tagareaname', 'core_tag'), get_string('component', 'tag'), get_string('tagareaenabled', 'core_tag'), get_string('tagcollection', 'tag'), get_string('showstandard', 'tag') . $OUTPUT->help_icon('showstandard', 'tag')); $this->data = array(); $this->rowclasses = array(); $tagareas = core_tag_area::get_areas(); $tagcollections = core_tag_collection::get_collections_menu(true); $tagcollectionsall = core_tag_collection::get_collections_menu(); $standardchoices = array(core_tag_tag::BOTH_STANDARD_AND_NOT => get_string('standardsuggest', 'tag'), core_tag_tag::STANDARD_ONLY => get_string('standardforce', 'tag'), core_tag_tag::HIDE_STANDARD => get_string('standardhide', 'tag')); foreach ($tagareas as $itemtype => $it) { foreach ($it as $component => $record) { $areaname = core_tag_area::display_name($record->component, $record->itemtype); $tmpl = new \core_tag\output\tagareaenabled($record); $enabled = $OUTPUT->render_from_template('core/inplace_editable', $tmpl->export_for_template($OUTPUT)); $tmpl = new \core_tag\output\tagareacollection($record); $collectionselect = $OUTPUT->render_from_template('core/inplace_editable', $tmpl->export_for_template($OUTPUT)); $tmpl = new \core_tag\output\tagareashowstandard($record); $showstandardselect = $OUTPUT->render_from_template('core/inplace_editable', $tmpl->export_for_template($OUTPUT)); $this->data[] = array($areaname, $record->component === 'core' || preg_match('/^core_/', $record->component) ? get_string('coresystem') : get_string('pluginname', $record->component), $enabled, $collectionselect, $showstandardselect); $this->rowclasses[] = $record->enabled ? '' : 'dimmed_text'; } } }
/** * Constructor * * @param string|moodle_url $pageurl */ public function __construct($pageurl) { global $OUTPUT; parent::__construct(); $this->attributes['class'] = 'generaltable tag-areas-table'; $this->head = array(get_string('tagareaname', 'core_tag'), get_string('component', 'tag'), get_string('tagareaenabled', 'core_tag'), get_string('tagcollection', 'tag')); $this->data = array(); $this->rowclasses = array(); $tagareas = core_tag_area::get_areas(); $tagcollections = core_tag_collection::get_collections_menu(true); $tagcollectionsall = core_tag_collection::get_collections_menu(); foreach ($tagareas as $itemtype => $it) { foreach ($it as $component => $record) { $areaname = core_tag_area::display_name($record->component, $record->itemtype); $baseurl = new moodle_url($pageurl, array('ta' => $record->id, 'sesskey' => sesskey())); if ($record->enabled) { $enableurl = new moodle_url($baseurl, array('action' => 'areadisable')); $enabled = html_writer::link($enableurl, $OUTPUT->pix_icon('i/hide', get_string('disable'))); } else { $enableurl = new moodle_url($baseurl, array('action' => 'areaenable')); $enabled = html_writer::link($enableurl, $OUTPUT->pix_icon('i/show', get_string('enable'))); } if ($record->enabled && empty($record->locked) && count($tagcollections) > 1) { $changecollurl = new moodle_url($baseurl, array('action' => 'areasetcoll')); $select = new single_select($changecollurl, 'areacollid', $tagcollections, $record->tagcollid, null); $select->set_label(get_string('changetagcoll', 'core_tag', $areaname), array('class' => 'accesshide')); $collectionselect = $OUTPUT->render($select); } else { $collectionselect = $tagcollectionsall[$record->tagcollid]; } $this->data[] = array($areaname, $record->component === 'core' || preg_match('/^core_/', $record->component) ? get_string('coresystem') : get_string('pluginname', $record->component), $enabled, $collectionselect); $this->rowclasses[] = $record->enabled ? '' : 'dimmed_text'; } } }
/** * Updates the value in database and returns itself, called from inplace_editable callback * * @param int $itemid * @param mixed $newvalue * @return \self */ public static function update($itemid, $newvalue) { global $DB; require_capability('moodle/tag:manage', context_system::instance()); $tagarea = $DB->get_record('tag_area', array('id' => $itemid), '*', MUST_EXIST); $newvalue = $newvalue ? 1 : 0; $data = array('enabled' => $newvalue); \core_tag_area::update($tagarea, $data); $tagarea->enabled = $newvalue; $tmpl = new self($tagarea); return $tmpl; }
/** * 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; }
/** * Deletes a custom tag collection * * @param stdClass $tagcoll existing record in DB table tag_coll * @return bool wether the tag collection was deleted */ public static function delete($tagcoll) { global $DB, $CFG; $defaulttagcollid = self::get_default(); if ($tagcoll->id == $defaulttagcollid) { return false; } // Move all tags from this tag collection to the default one. $allitemtypes = core_tag_area::get_areas($tagcoll->id); foreach ($allitemtypes as $it) { foreach ($it as $v) { core_tag_area::update($v, array('tagcollid' => $defaulttagcollid)); } } // Delete tags from this tag_coll. core_tag_tag::delete_tags($DB->get_fieldset_select('tag', 'id', 'tagcollid = ?', array($tagcoll->id))); // Delete the tag collection. $DB->delete_records('tag_coll', array('id' => $tagcoll->id)); // Reset cache. cache::make('core', 'tags')->delete('tag_coll'); \core\event\tag_collection_deleted::create_from_record($tagcoll)->trigger(); return true; }
break; case 'areasetcoll': if ($tagarea) { require_sesskey(); if ($newtagcollid = optional_param('areacollid', null, PARAM_INT)) { core_tag_area::update($tagarea, array('tagcollid' => $newtagcollid)); redirect(new moodle_url($manageurl, array('notice' => 'changessaved'))); } } redirect($manageurl); break; case 'areasetshowstandard': if ($tagarea) { require_sesskey(); if (($showstandard = optional_param('showstandard', null, PARAM_INT)) !== null) { core_tag_area::update($tagarea, array('showstandard' => $showstandard)); redirect(new moodle_url($manageurl, array('notice' => 'changessaved'))); } } redirect($manageurl); break; case 'delete': require_sesskey(); if (!$tagschecked && $tagid) { $tagschecked = array($tagid); } core_tag_tag::delete_tags($tagschecked); redirect(new moodle_url($PAGE->url, $tagschecked ? array('notice' => 'deleted') : null)); break; case 'setflag': require_sesskey();
$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; }
/** * Returns the list of tag links available for the current user (edit, flag, etc.) * * @return array */ public function get_links() { global $USER; $links = array(); if (!isloggedin() || isguestuser()) { return $links; } $tagname = $this->get_display_name(); $systemcontext = context_system::instance(); // Add a link for users to add/remove this from their interests. if (static::is_enabled('core', 'user') && core_tag_area::get_collection('core', 'user') == $this->tagcollid) { if (static::is_item_tagged_with('core', 'user', $USER->id, $this->name)) { $url = new moodle_url('/tag/user.php', array('action' => 'removeinterest', 'sesskey' => sesskey(), 'tag' => $this->rawname)); $links[] = html_writer::link($url, get_string('removetagfrommyinterests', 'tag', $tagname), array('class' => 'removefrommyinterests')); } else { $url = new moodle_url('/tag/user.php', array('action' => 'addinterest', 'sesskey' => sesskey(), 'tag' => $this->rawname)); $links[] = html_writer::link($url, get_string('addtagtomyinterests', 'tag', $tagname), array('class' => 'addtomyinterests')); } } // Flag as inappropriate link. Only people with moodle/tag:flag capability. if (has_capability('moodle/tag:flag', $systemcontext)) { $url = new moodle_url('/tag/user.php', array('action' => 'flaginappropriate', 'sesskey' => sesskey(), 'id' => $this->id)); $links[] = html_writer::link($url, get_string('flagasinappropriate', 'tag', $tagname), array('class' => 'flagasinappropriate')); } // Edit tag: Only people with moodle/tag:edit capability who either have it as an interest or can manage tags. if (has_capability('moodle/tag:edit', $systemcontext) || has_capability('moodle/tag:manage', $systemcontext)) { $url = new moodle_url('/tag/edit.php', array('id' => $this->id)); $links[] = html_writer::link($url, get_string('edittag', 'tag'), array('class' => 'edittag')); } return $links; }
/** * Finds the tag collection to use for standard tag selector * * @return int */ protected function get_tag_collection() { if (empty($this->tagsoptions['tagcollid']) && (empty($this->tagsoptions['itemtype']) || empty($this->tagsoptions['component']))) { debugging('You need to specify \'itemtype\' and \'component\' of the tagged ' . 'area in the tags form element options', DEBUG_DEVELOPER); } if (!empty($this->tagsoptions['tagcollid'])) { return $this->tagsoptions['tagcollid']; } if ($this->tagsoptions['itemtype']) { $this->tagsoptions['tagcollid'] = core_tag_area::get_collection($this->tagsoptions['component'], $this->tagsoptions['itemtype']); } else { $this->tagsoptions['tagcollid'] = core_tag_collection::get_default(); } return $this->tagsoptions['tagcollid']; }
/** * Upgrade moodle core * @param float $version target version * @param bool $verbose * @return void, may throw exception */ function upgrade_core($version, $verbose) { global $CFG, $SITE, $DB, $COURSE; raise_memory_limit(MEMORY_EXTRA); require_once $CFG->libdir . '/db/upgrade.php'; // Defines upgrades try { // Reset caches before any output. cache_helper::purge_all(true); purge_all_caches(); // Upgrade current language pack if we can upgrade_language_pack(); print_upgrade_part_start('moodle', false, $verbose); // Pre-upgrade scripts for local hack workarounds. $preupgradefile = "{$CFG->dirroot}/local/preupgrade.php"; if (file_exists($preupgradefile)) { core_php_time_limit::raise(); require $preupgradefile; // Reset upgrade timeout to default. upgrade_set_timeout(); } $result = xmldb_main_upgrade($CFG->version); if ($version > $CFG->version) { // store version if not already there upgrade_main_savepoint($result, $version, false); } // In case structure of 'course' table has been changed and we forgot to update $SITE, re-read it from db. $SITE = $DB->get_record('course', array('id' => $SITE->id)); $COURSE = clone $SITE; // perform all other component upgrade routines update_capabilities('moodle'); log_update_descriptions('moodle'); external_update_descriptions('moodle'); events_update_definition('moodle'); \core\task\manager::reset_scheduled_tasks_for_component('moodle'); message_update_providers('moodle'); \core\message\inbound\manager::update_handlers_for_component('moodle'); core_tag_area::reset_definitions_for_component('moodle'); // Update core definitions. cache_helper::update_definitions(true); // Purge caches again, just to be sure we arn't holding onto old stuff now. cache_helper::purge_all(true); purge_all_caches(); // Clean up contexts - more and more stuff depends on existence of paths and contexts context_helper::cleanup_instances(); context_helper::create_instances(null, false); context_helper::build_all_paths(false); $syscontext = context_system::instance(); $syscontext->mark_dirty(); print_upgrade_part_end('moodle', false, $verbose); } catch (Exception $ex) { upgrade_handle_exception($ex); } catch (Throwable $ex) { // Engine errors in PHP7 throw exceptions of type Throwable (this "catch" will be ignored in PHP5). upgrade_handle_exception($ex); } }
$params['tc'] = $tagcollid; } if ($filter !== '') { $params['filter'] = $filter; } admin_externalpage_setup('managetags', '', $params, '', array('pagelayout' => 'report')); if (empty($CFG->usetags)) { print_error('tagsaredisabled', 'tag'); } $tagobject = null; if ($tagid) { $tagobject = core_tag_tag::get($tagid, '*', MUST_EXIST); $tagcollid = $tagobject->tagcollid; } $tagcoll = core_tag_collection::get_by_id($tagcollid); $tagarea = core_tag_area::get_by_id($tagareaid); $manageurl = new moodle_url('/tag/manage.php'); if ($tagcoll) { // We are inside a tag collection - add it to the breadcrumb. $PAGE->navbar->add(core_tag_collection::display_name($tagcoll), new moodle_url($manageurl, array('tc' => $tagcoll->id))); } $PAGE->set_blocks_editing_capability('moodle/tag:editblocks'); switch ($action) { case 'colladd': require_sesskey(); $name = required_param('name', PARAM_NOTAGS); $searchable = required_param('searchable', PARAM_BOOL); core_tag_collection::create(array('name' => $name, 'searchable' => $searchable)); redirect($manageurl); break; case 'colldelete':
/** * Renders the tag index page * * @param core_tag_tag $tag * @param \core_tag\output\tagindex[] $entities * @param int $tagareaid * @param bool $exclusivemode if set to true it means that no other entities tagged with this tag * are displayed on the page and the per-page limit may be bigger * @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 to search for records * @param bool $rec search in subcontexts as well * @param int $page 0-based number of page being displayed * @return string */ public function tag_index_page($tag, $entities, $tagareaid, $exclusivemode, $fromctx, $ctx, $rec, $page) { global $CFG, $OUTPUT; $this->page->requires->js_call_amd('core/tag', 'init_tagindex_page'); $tagname = $tag->get_display_name(); $systemcontext = context_system::instance(); if ($tag->flag > 0 && has_capability('moodle/tag:manage', $systemcontext)) { $tagname = '<span class="flagged-tag">' . $tagname . '</span>'; } $rv = ''; $rv .= $this->output->heading($tagname, 2); $rv .= $this->tag_links($tag); if ($desciption = $tag->get_formatted_description()) { $rv .= $this->output->box($desciption, 'generalbox tag-description'); } $relatedtagslimit = 10; $relatedtags = $tag->get_related_tags(); $taglist = new \core_tag\output\taglist($relatedtags, get_string('relatedtags', 'tag'), 'tag-relatedtags', $relatedtagslimit); $rv .= $OUTPUT->render_from_template('core_tag/taglist', $taglist->export_for_template($OUTPUT)); // Display quick menu of the item types (if more than one item type found). $entitylinks = array(); foreach ($entities as $entity) { if (!empty($entity->hascontent)) { $entitylinks[] = '<li><a href="#' . $entity->anchor . '">' . core_tag_area::display_name($entity->component, $entity->itemtype) . '</a></li>'; } } if (count($entitylinks) > 1) { $rv .= '<div class="tag-index-toc"><ul class="inline-list">' . join('', $entitylinks) . '</ul></div>'; } else { if (!$entitylinks) { $rv .= '<div class="tag-noresults">' . get_string('noresultsfor', 'tag', $tagname) . '</div>'; } } // Display entities tagged with the tag. $content = ''; foreach ($entities as $entity) { if (!empty($entity->hascontent)) { $content .= $this->output->render_from_template('core_tag/index', $entity->export_for_template($this->output)); } } if ($exclusivemode) { $rv .= $content; } else { if ($content) { $rv .= html_writer::div($content, 'tag-index-items'); } } // Display back link if we are browsing one tag area. if ($tagareaid) { $url = $tag->get_view_url(0, $fromctx, $ctx, $rec); $rv .= '<div class="tag-backtoallitems">' . html_writer::link($url, get_string('backtoallitems', 'tag', $tag->get_display_name())) . '</div>'; } return $rv; }
/** * Test the tag created event. */ public function test_tag_created() { global $DB; // Trigger and capture the event for creating a tag. $sink = $this->redirectEvents(); core_tag_tag::create_if_missing(core_tag_area::get_collection('core', 'course'), array('A really awesome tag!')); $events = $sink->get_events(); $event = reset($events); // Check that the tag was created and the event data is valid. $this->assertEquals(1, $DB->count_records('tag')); $this->assertInstanceOf('\\core\\event\\tag_created', $event); $this->assertEquals(context_system::instance(), $event->get_context()); }
break; case 'areaenable': case 'areadisable': if ($tagarea) { require_sesskey(); $data = array('enabled' => $action === 'areaenable' ? 1 : 0); core_tag_area::update($tagarea, $data); redirect(new moodle_url($manageurl, array('notice' => 'changessaved'))); } redirect($manageurl); break; case 'areasetcoll': if ($tagarea) { require_sesskey(); if ($newtagcollid = optional_param('areacollid', null, PARAM_INT)) { core_tag_area::update($tagarea, array('tagcollid' => $newtagcollid)); redirect(new moodle_url($manageurl, array('notice' => 'changessaved'))); } } redirect($manageurl); break; case 'delete': require_sesskey(); if (!$tagschecked && $tagid) { $tagschecked = array($tagid); } core_tag_tag::delete_tags($tagschecked); redirect(new moodle_url($PAGE->url, $tagschecked ? array('notice' => 'deleted') : null)); break; case 'setflag': require_sesskey();
/** * Prints a box that contains the management links of a tag * * @deprecated since 3.1 * @param core_tag_tag|stdClass $tag_object * @param bool $return if true the function will return the generated tag cloud instead of displaying it. * @return string|null a HTML string or null if this function does the output */ function tag_print_management_box($tag_object, $return = false) { global $USER, $CFG, $OUTPUT; debugging('Function tag_print_description_box() is deprecated without replacement. ' . 'See core_tag_renderer for similar code.', DEBUG_DEVELOPER); $tagname = core_tag_tag::make_display_name($tag_object); $output = ''; if (!isguestuser()) { $output .= $OUTPUT->box_start('box', 'tag-management-box'); $systemcontext = context_system::instance(); $links = array(); // Add a link for users to add/remove this from their interests if (core_tag_tag::is_enabled('core', 'user') && core_tag_area::get_collection('core', 'user') == $tag_object->tagcollid) { if (core_tag_tag::is_item_tagged_with('core', 'user', $USER->id, $tag_object->name)) { $links[] = '<a href="' . $CFG->wwwroot . '/tag/user.php?action=removeinterest&sesskey=' . sesskey() . '&tag=' . rawurlencode($tag_object->name) . '">' . get_string('removetagfrommyinterests', 'tag', $tagname) . '</a>'; } else { $links[] = '<a href="' . $CFG->wwwroot . '/tag/user.php?action=addinterest&sesskey=' . sesskey() . '&tag=' . rawurlencode($tag_object->name) . '">' . get_string('addtagtomyinterests', 'tag', $tagname) . '</a>'; } } // Flag as inappropriate link. Only people with moodle/tag:flag capability. if (has_capability('moodle/tag:flag', $systemcontext)) { $links[] = '<a href="' . $CFG->wwwroot . '/tag/user.php?action=flaginappropriate&sesskey=' . sesskey() . '&id=' . $tag_object->id . '">' . get_string('flagasinappropriate', 'tag', rawurlencode($tagname)) . '</a>'; } // Edit tag: Only people with moodle/tag:edit capability who either have it as an interest or can manage tags if (has_capability('moodle/tag:edit', $systemcontext) || has_capability('moodle/tag:manage', $systemcontext)) { $links[] = '<a href="' . $CFG->wwwroot . '/tag/edit.php?id=' . $tag_object->id . '">' . get_string('edittag', 'tag') . '</a>'; } $output .= implode(' | ', $links); $output .= $OUTPUT->box_end(); } if ($return) { return $output; } else { echo $output; } }
public function test_move_tags_corrupted() { global $DB; list($collid1, $collid2, $user1, $user2, $blogpost) = $this->prepare_move_tags(); $collid3 = core_tag_collection::create(array('name' => 'weirdcoll'))->id; // We already have Tag1 in coll1, now let's create it in coll3. $extratag1 = $this->getDataGenerator()->create_tag(array('rawname' => 'Tag1', 'tagcollid' => $collid3, 'tagtype' => 'official')); // Artificially add 'Tag1' from coll3 to user2. $DB->insert_record('tag_instance', array('tagid' => $extratag1->id, 'itemtype' => 'user', 'component' => 'core', 'itemid' => $user2->id, 'ordering' => 3)); // Now we have corrupted data: both users are tagged with 'Tag1', however these are two tags in different collections. $user1tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user1->id)); $user2tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user2->id)); $this->assertEquals('Tag1', $user1tags[0]->rawname); $this->assertEquals('Tag1', $user2tags[2]->rawname); $this->assertNotEquals($user1tags[0]->tagcollid, $user2tags[2]->tagcollid); // Move user interests tag area into coll2. $tagarea = $DB->get_record('tag_area', array('itemtype' => 'user', 'component' => 'core')); core_tag_area::update($tagarea, array('tagcollid' => $collid2)); // Now all tags are correctly moved to the new collection and both tags 'Tag1' were merged. $user1tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user1->id)); $user2tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user2->id)); $this->assertEquals('Tag1', $user1tags[0]->rawname); $this->assertEquals('Tag1', $user2tags[2]->rawname); $this->assertEquals($collid2, $user1tags[0]->tagcollid); $this->assertEquals($collid2, $user2tags[2]->tagcollid); }
/** * Automatically clean-up all plugin data and remove the plugin DB tables * * NOTE: do not call directly, use new /admin/plugins.php?uninstall=component instead! * * @param string $type The plugin type, eg. 'mod', 'qtype', 'workshopgrading' etc. * @param string $name The plugin name, eg. 'forum', 'multichoice', 'accumulative' etc. * @uses global $OUTPUT to produce notices and other messages * @return void */ function uninstall_plugin($type, $name) { global $CFG, $DB, $OUTPUT; // This may take a long time. core_php_time_limit::raise(); // Recursively uninstall all subplugins first. $subplugintypes = core_component::get_plugin_types_with_subplugins(); if (isset($subplugintypes[$type])) { $base = core_component::get_plugin_directory($type, $name); if (file_exists("{$base}/db/subplugins.php")) { $subplugins = array(); include "{$base}/db/subplugins.php"; foreach ($subplugins as $subplugintype => $dir) { $instances = core_component::get_plugin_list($subplugintype); foreach ($instances as $subpluginname => $notusedpluginpath) { uninstall_plugin($subplugintype, $subpluginname); } } } } $component = $type . '_' . $name; // eg. 'qtype_multichoice' or 'workshopgrading_accumulative' or 'mod_forum' if ($type === 'mod') { $pluginname = $name; // eg. 'forum' if (get_string_manager()->string_exists('modulename', $component)) { $strpluginname = get_string('modulename', $component); } else { $strpluginname = $component; } } else { $pluginname = $component; if (get_string_manager()->string_exists('pluginname', $component)) { $strpluginname = get_string('pluginname', $component); } else { $strpluginname = $component; } } echo $OUTPUT->heading($pluginname); // Delete all tag areas, collections and instances associated with this plugin. core_tag_area::uninstall($component); // Custom plugin uninstall. $plugindirectory = core_component::get_plugin_directory($type, $name); $uninstalllib = $plugindirectory . '/db/uninstall.php'; if (file_exists($uninstalllib)) { require_once $uninstalllib; $uninstallfunction = 'xmldb_' . $pluginname . '_uninstall'; // eg. 'xmldb_workshop_uninstall()' if (function_exists($uninstallfunction)) { // Do not verify result, let plugin complain if necessary. $uninstallfunction(); } } // Specific plugin type cleanup. $plugininfo = core_plugin_manager::instance()->get_plugin_info($component); if ($plugininfo) { $plugininfo->uninstall_cleanup(); core_plugin_manager::reset_caches(); } $plugininfo = null; // perform clean-up task common for all the plugin/subplugin types //delete the web service functions and pre-built services require_once $CFG->dirroot . '/lib/externallib.php'; external_delete_descriptions($component); // delete calendar events $DB->delete_records('event', array('modulename' => $pluginname)); // Delete scheduled tasks. $DB->delete_records('task_scheduled', array('component' => $pluginname)); // Delete Inbound Message datakeys. $DB->delete_records_select('messageinbound_datakeys', 'handler IN (SELECT id FROM {messageinbound_handlers} WHERE component = ?)', array($pluginname)); // Delete Inbound Message handlers. $DB->delete_records('messageinbound_handlers', array('component' => $pluginname)); // delete all the logs $DB->delete_records('log', array('module' => $pluginname)); // delete log_display information $DB->delete_records('log_display', array('component' => $component)); // delete the module configuration records unset_all_config_for_plugin($component); if ($type === 'mod') { unset_all_config_for_plugin($pluginname); } // delete message provider message_provider_uninstall($component); // delete the plugin tables $xmldbfilepath = $plugindirectory . '/db/install.xml'; drop_plugin_tables($component, $xmldbfilepath, false); if ($type === 'mod' or $type === 'block') { // non-frankenstyle table prefixes drop_plugin_tables($name, $xmldbfilepath, false); } // delete the capabilities that were defined by this module capabilities_cleanup($component); // remove event handlers and dequeue pending events events_uninstall($component); // Delete all remaining files in the filepool owned by the component. $fs = get_file_storage(); $fs->delete_component_files($component); // Finally purge all caches. purge_all_caches(); // Invalidate the hash used for upgrade detections. set_config('allversionshash', ''); echo $OUTPUT->notification(get_string('success'), 'notifysuccess'); }