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); }
/** * Update the database to contain a list of tagged areas for a component. * The list of tagged areas is read from [plugindir]/db/tag.php * * @param string $componentname - The frankenstyle component name. */ public static function reset_definitions_for_component($componentname) { global $DB; $dir = core_component::get_component_directory($componentname); $file = $dir . '/db/tag.php'; $tagareas = null; if (file_exists($file)) { require_once $file; } list($a, $b) = core_component::normalize_component($componentname); $component = $b ? $a . '_' . $b : $a; list($existingareas, $existingcolls) = self::get_definitions_for_component($componentname); $itemtypes = array(); $collections = array(); $needcleanup = false; if ($tagareas) { foreach ($tagareas as $tagarea) { $record = (object) $tagarea; if ($component !== 'core' || empty($record->component)) { if (isset($record->component) && $record->component !== $component) { debugging("Item type {$record->itemtype} has illegal component {$record->component}", DEBUG_DEVELOPER); } $record->component = $component; } unset($record->tagcollid); if (!empty($record->collection)) { // Create collection if it does not exist, or update 'searchable' and/or 'customurl' if needed. $key = $record->collection . ':' . $record->component; $collectiondata = array_intersect_key((array) $record, array('component' => 1, 'searchable' => 1, 'customurl' => 1)); $collectiondata['name'] = $record->collection; if (!array_key_exists($key, $existingcolls)) { $existingcolls[$key] = core_tag_collection::create($collectiondata); } else { core_tag_collection::update($existingcolls[$key], $collectiondata); } $record->tagcollid = $existingcolls[$key]->id; $collections[$key] = $existingcolls[$key]; unset($record->collection); } unset($record->searchable); unset($record->customurl); if (!isset($record->callback)) { $record->callback = null; } if (!isset($record->callbackfile)) { $record->callbackfile = null; } $itemtypes[$record->itemtype . ':' . $record->component] = $record; } } $todeletearea = array_diff_key($existingareas, $itemtypes); $todeletecoll = array_diff_key($existingcolls, $collections); // Delete tag areas that are no longer needed. foreach ($todeletearea as $key => $record) { self::delete($record); } // Update tag areas if changed. $toupdatearea = array_intersect_key($existingareas, $itemtypes); foreach ($toupdatearea as $key => $tagarea) { if (!isset($itemtypes[$key]->tagcollid)) { foreach ($todeletecoll as $tagcoll) { if ($tagcoll->id == $tagarea->tagcollid) { $itemtypes[$key]->tagcollid = core_tag_collection::get_default(); } } } self::update($tagarea, $itemtypes[$key]); } // Create new tag areas. $toaddarea = array_diff_key($itemtypes, $existingareas); foreach ($toaddarea as $record) { self::create($record); } // Delete tag collections that are no longer needed. foreach ($todeletecoll as $key => $tagcoll) { core_tag_collection::delete($tagcoll); } }
// We are inside a tag collection - add it to the page url and the breadcrumb. $PAGE->set_url(new moodle_url($PAGE->url, array('tc' => $tagcoll->id))); $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': case 'colledit': if ($action === 'colladd' || $action === 'colledit' && $tagcoll && empty($tagcoll->component)) { $form = new core_tag_collection_form($manageurl, $tagcoll); if ($form->is_cancelled()) { redirect($manageurl); } else { if ($data = $form->get_data()) { if ($action === 'colladd') { core_tag_collection::create($data); } else { core_tag_collection::update($tagcoll, $data); } redirect($manageurl); } else { $title = $action === 'colladd' ? get_string('addtagcoll', 'tag') : get_string('edittagcoll', 'tag', core_tag_collection::display_name($tagcoll)); $PAGE->navbar->add($title); echo $OUTPUT->header(); echo $OUTPUT->heading($title, 2); $form->display(); echo $OUTPUT->footer(); exit; } } }
$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': if ($tagcoll && !$tagcoll->component) { require_sesskey(); core_tag_collection::delete($tagcoll); \core\notification::success(get_string('changessaved', 'core_tag')); } redirect($manageurl); break; case 'collmoveup': if ($tagcoll) { require_sesskey(); core_tag_collection::change_sortorder($tagcoll, -1); redirect($manageurl, get_string('changessaved', 'core_tag'), null, \core\output\notification::NOTIFY_SUCCESS);