/** * 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'; } } }
/** * 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'; } } }
/** * 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()); $tagcoll = $DB->get_record('tag_coll', array('id' => $itemid), '*', MUST_EXIST); \core_tag_collection::update($tagcoll, array('name' => $newvalue)); return new self($tagcoll); }
/** * 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 = clean_param($newvalue, PARAM_INT); $tagcollections = \core_tag_collection::get_collections_menu(true); if (!array_key_exists($newvalue, $tagcollections)) { throw new \moodle_exception('invalidparameter', 'debug'); } $data = array('tagcollid' => $newvalue); core_tag_area::update($tagarea, $data); $tagarea->tagcollid = $newvalue; $tmpl = new self($tagarea); return $tmpl; }
/** * Constructor * @param string|moodle_url $pageurl */ public function __construct($pageurl) { global $OUTPUT; parent::__construct(); $this->attributes['class'] = 'generaltable tag-collections-table'; $this->head = array(get_string('name'), get_string('component', 'tag'), get_string('tagareas', 'tag'), get_string('searchable', 'tag') . $OUTPUT->help_icon('searchable', 'tag'), ''); $this->data = array(); $tagcolls = core_tag_collection::get_collections(); $idx = 0; foreach ($tagcolls as $tagcoll) { $actions = ''; $name = core_tag_collection::display_name($tagcoll); $url = new moodle_url($pageurl, array('sesskey' => sesskey(), 'tc' => $tagcoll->id)); if (!$tagcoll->isdefault) { // Move up. if ($idx > 1) { $url->param('action', 'collmoveup'); $actions .= $OUTPUT->action_icon($url, new pix_icon('t/up', get_string('moveup')), null, array('class' => 'action-icon action_moveup')); } // Move down. if ($idx < count($tagcolls) - 1) { $url->param('action', 'collmovedown'); $actions .= $OUTPUT->action_icon($url, new pix_icon('t/down', get_string('movedown')), null, array('class' => 'action-icon action_movedown')); } } if (!$tagcoll->isdefault && empty($tagcoll->component)) { // Delete. $url->param('action', 'colldelete'); $actions .= $OUTPUT->action_icon('#', new pix_icon('t/delete', get_string('delete')), null, array('data-url' => $url->out(false), 'data-collname' => $name, 'class' => 'action-icon action_delete')); } $component = ''; if ($tagcoll->component) { $component = $tagcoll->component === 'core' || preg_match('/^core_/', $tagcoll->component) ? get_string('coresystem') : get_string('pluginname', $tagcoll->component); } $allareas = core_tag_collection::get_areas_names(null, false); $validareas = core_tag_collection::get_areas_names($tagcoll->id); $areaslist = array_map(function ($key) use($allareas, $validareas) { return "<li data-areaid=\"{$key}\" " . (array_key_exists($key, $validareas) ? "" : "style=\"display:none;\"") . ">{$allareas[$key]}</li>"; }, array_keys($allareas)); $displayname = new \core_tag\output\tagcollname($tagcoll); $searchable = new \core_tag\output\tagcollsearchable($tagcoll); $this->data[] = array($displayname->render($OUTPUT), $component, "<ul data-collectionid=\"{$tagcoll->id}\">" . join('', $areaslist) . '</ul>', $searchable->render($OUTPUT), $actions); $idx++; } }
/** * Constructor * @param string|moodle_url $pageurl */ public function __construct($pageurl) { global $OUTPUT; parent::__construct(); $this->attributes['class'] = 'generaltable tag-collections-table'; $this->head = array(get_string('name'), get_string('component', 'tag'), get_string('tagareas', 'tag'), get_string('searchable', 'tag') . $OUTPUT->help_icon('searchable', 'tag'), ''); $this->data = array(); $tagcolls = core_tag_collection::get_collections(); $idx = 0; foreach ($tagcolls as $tagcoll) { $actions = ''; $name = core_tag_collection::display_name($tagcoll); $url = new moodle_url($pageurl, array('sesskey' => sesskey(), 'tc' => $tagcoll->id)); if (!$tagcoll->isdefault) { // Move up. if ($idx > 1) { $url->param('action', 'collmoveup'); $actions .= $OUTPUT->action_icon($url, new pix_icon('t/up', get_string('moveup'))); } // Move down. if ($idx < count($tagcolls) - 1) { $url->param('action', 'collmovedown'); $actions .= $OUTPUT->action_icon($url, new pix_icon('t/down', get_string('movedown'))); } } if (empty($tagcoll->component)) { // Edit. $url->param('action', 'colledit'); $actions .= $OUTPUT->action_icon($url, new pix_icon('t/edit', get_string('edittagcoll', 'tag', $name))); } if (!$tagcoll->isdefault && empty($tagcoll->component)) { // Delete. $url->param('action', 'colldelete'); $actions .= $OUTPUT->action_icon($url, new pix_icon('t/delete', get_string('delete'))); } $manageurl = new moodle_url('/tag/manage.php', array('tc' => $tagcoll->id)); $component = ''; if ($tagcoll->component) { $component = $tagcoll->component === 'core' || preg_match('/^core_/', $tagcoll->component) ? get_string('coresystem') : get_string('pluginname', $tagcoll->component); } $this->data[] = array(html_writer::link($manageurl, $name), $component, join(', ', core_tag_collection::get_areas_names($tagcoll->id)), $tagcoll->searchable ? get_string('yes') : '-', $actions); $idx++; } }
/** * Add the tag collection selector * * @param object $mform the form being built. */ protected function add_collection_selector($mform) { $tagcolls = core_tag_collection::get_collections_menu(false, false, get_string('anycollection', 'block_tags')); if (count($tagcolls) <= 1) { return; } $tagcollssearchable = core_tag_collection::get_collections_menu(false, true); $hasunsearchable = false; foreach ($tagcolls as $id => $name) { if ($id && !array_key_exists($id, $tagcollssearchable)) { $hasunsearchable = true; $tagcolls[$id] = $name . '*'; } } $mform->addElement('select', 'config_tagcoll', get_string('tagcollection', 'block_tags'), $tagcolls); if ($hasunsearchable) { $mform->addHelpButton('config_tagcoll', 'tagcollection', 'block_tags'); } $mform->setDefault('config_tagcoll', 0); }
/** * Search for tags with names that match some text * * @package core_tag * @deprecated since 3.1 * @param string $text escaped string that the tag names will be matched against * @param bool $ordered If true, tags are ordered by their popularity. If false, no ordering. * @param int/string $limitfrom (optional, required if $limitnum is set) return a subset of records, starting at this point. * @param int/string $limitnum (optional, required if $limitfrom is set) return a subset comprising this many records. * @param int $tagcollid * @return array/boolean an array of objects, or false if no records were found or an error occured. */ function tag_find_tags($text, $ordered = true, $limitfrom = '', $limitnum = '', $tagcollid = null) { debugging('Method tag_find_tags() is deprecated without replacement', DEBUG_DEVELOPER); global $DB; $text = core_text::strtolower(clean_param($text, PARAM_TAG)); list($sql, $params) = $DB->get_in_or_equal($tagcollid ? array($tagcollid) : array_keys(core_tag_collection::get_collections(true))); array_unshift($params, "%{$text}%"); if ($ordered) { $query = "SELECT tg.id, tg.name, tg.rawname, tg.tagcollid, COUNT(ti.id) AS count\n FROM {tag} tg LEFT JOIN {tag_instance} ti ON tg.id = ti.tagid\n WHERE tg.name LIKE ? AND tg.tagcollid {$sql}\n GROUP BY tg.id, tg.name, tg.rawname\n ORDER BY count DESC"; } else { $query = "SELECT tg.id, tg.name, tg.rawname, tg.tagcollid\n FROM {tag} tg\n WHERE tg.name LIKE ? AND tg.tagcollid {$sql}"; } return $DB->get_records_sql($query, $params, $limitfrom, $limitnum); }
/** * Returns the list of tags with number of items tagged * * @param int $tagcollid * @param null|bool $isstandard return only standard tags * @param int $limit maximum number of tags to retrieve, tags are sorted by the instance count * descending here regardless of $sort parameter * @param string $sort sort order for display, default 'name' - tags will be sorted after they are retrieved * @param string $search search string * @param int $fromctx context id where this tag cloud is displayed * @param int $ctx only retrieve tag instances in this context * @param int $rec retrieve tag instances in the $ctx context and it's children (default 1) * @return \core_tag\output\tagcloud */ public static function get_tag_cloud($tagcollid, $isstandard = false, $limit = 150, $sort = 'name', $search = '', $fromctx = 0, $ctx = 0, $rec = 1) { global $DB; $fromclause = 'FROM {tag_instance} ti JOIN {tag} tg ON tg.id = ti.tagid'; $whereclause = 'WHERE ti.itemtype <> \'tag\''; list($sql, $params) = $DB->get_in_or_equal($tagcollid ? array($tagcollid) : array_keys(self::get_collections(true))); $whereclause .= ' AND tg.tagcollid ' . $sql; if ($isstandard) { $whereclause .= ' AND tg.isstandard = 1'; } $context = $ctx ? context::instance_by_id($ctx) : context_system::instance(); if ($rec && $context->contextlevel != CONTEXT_SYSTEM) { $fromclause .= ' JOIN {context} ctx ON ctx.id = ti.contextid '; $whereclause .= ' AND ctx.path LIKE ?'; $params[] = $context->path . '%'; } else { if (!$rec) { $whereclause .= ' AND ti.contextid = ?'; $params[] = $context->id; } } if (strval($search) !== '') { $whereclause .= ' AND tg.name LIKE ?'; $params[] = '%' . core_text::strtolower($search) . '%'; } $tagsincloud = $DB->get_records_sql("SELECT tg.id, tg.rawname, tg.name, tg.isstandard, COUNT(ti.id) AS count, tg.flag, tg.tagcollid\n {$fromclause}\n {$whereclause}\n GROUP BY tg.id, tg.rawname, tg.name, tg.flag, tg.isstandard, tg.tagcollid\n ORDER BY count DESC, tg.name ASC", $params, 0, $limit); $tagscount = count($tagsincloud); if ($tagscount == $limit) { $tagscount = $DB->get_field_sql("SELECT COUNT(DISTINCT tg.id) {$fromclause} {$whereclause}", $params); } self::$cloudsortfield = $sort; usort($tagsincloud, "self::cloud_sort"); return new core_tag\output\tagcloud($tagsincloud, $tagscount, $fromctx, $ctx, $rec); }
/** * 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); }
} if (!$tagcoll) { // Tag collection is not specified. Display the overview of tag collections and tag areas. $tagareastable = new core_tag_areas_table($manageurl); $colltable = new core_tag_collections_table($manageurl); echo $OUTPUT->heading(get_string('tagcollections', 'core_tag') . $OUTPUT->help_icon('tagcollection', 'tag'), 3); echo html_writer::table($colltable); $url = new moodle_url($manageurl, array('action' => 'colladd')); echo html_writer::div(html_writer::link($url, get_string('addtagcoll', 'tag')), 'mdl-right addtagcoll'); echo $OUTPUT->heading(get_string('tagareas', 'core_tag'), 3); echo html_writer::table($tagareastable); echo $OUTPUT->footer(); exit; } // Tag collection is specified. Manage tags in this collection. echo $OUTPUT->heading(core_tag_collection::display_name($tagcoll)); // Small form to add an standard tag. print '<form class="tag-addtags-form" method="post" action="' . $CFG->wwwroot . '/tag/manage.php">'; print '<input type="hidden" name="tc" value="' . $tagcollid . '" />'; print '<input type="hidden" name="action" value="addstandardtag" />'; print '<input type="hidden" name="perpage" value="' . $perpage . '" />'; print '<input type="hidden" name="page" value="' . $page . '" />'; print '<div class="tag-management-form generalbox"><label class="accesshide" for="id_otagsadd">' . get_string('addotags', 'tag') . '</label>' . '<input name="otagsadd" id="id_otagsadd" type="text" />' . '<input type="hidden" name="sesskey" value="' . sesskey() . '">' . '<input name="addotags" value="' . get_string('addotags', 'tag') . '" onclick="skipClientValidation = true;" id="id_addotags" type="submit" />' . '</div>'; print '</form>'; $table = new core_tag_manage_table($tagcollid); echo '<form class="tag-management-form" method="post" action="' . $CFG->wwwroot . '/tag/manage.php">'; echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'tc', 'value' => $tagcollid)); echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())); echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'action', 'value' => 'delete')); echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'perpage', 'value' => $perpage)); echo html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'page', 'value' => $page));
/** * 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); }
/** * Creates a URL to view a tag * * @param int $tagcollid * @param string $name * @param int $exclusivemode * @param int $fromctx context id where this tag cloud is displayed * @param int $ctx context id for tag view link * @param int $rec recursive argument for tag view link * @return \moodle_url */ public static function make_url($tagcollid, $name, $exclusivemode = 0, $fromctx = 0, $ctx = 0, $rec = 1) { $coll = core_tag_collection::get_by_id($tagcollid); if (!empty($coll->customurl)) { $url = '/' . ltrim(trim($coll->customurl), '/'); } else { $url = '/tag/index.php'; } $params = array('tc' => $tagcollid, 'tag' => $name); if ($exclusivemode) { $params['excl'] = 1; } if ($fromctx) { $params['from'] = $fromctx; } if ($ctx) { $params['ctx'] = $ctx; } if (!$rec) { $params['rec'] = 0; } return new moodle_url($url, $params); }
/** * 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']; }
public function get_content() { global $CFG, $COURSE, $USER, $SCRIPT, $OUTPUT; if (empty($CFG->usetags)) { $this->content = new stdClass(); $this->content->text = ''; if ($this->page->user_is_editing()) { $this->content->text = get_string('disabledtags', 'block_tags'); } return $this->content; } if (!isset($this->config)) { $this->config = new stdClass(); } if (empty($this->config->numberoftags)) { $this->config->numberoftags = 80; } if (empty($this->config->showstandard)) { $this->config->showstandard = core_tag_tag::BOTH_STANDARD_AND_NOT; } if (empty($this->config->ctx)) { $this->config->ctx = 0; } if (empty($this->config->rec)) { $this->config->rec = 1; } if (empty($this->config->tagcoll)) { $this->config->tagcoll = 0; } if ($this->content !== NULL) { return $this->content; } if (empty($this->instance)) { $this->content = ''; return $this->content; } $this->content = new stdClass(); $this->content->text = ''; $this->content->footer = ''; // Get a list of tags. $tagcloud = core_tag_collection::get_tag_cloud($this->config->tagcoll, $this->config->showstandard == core_tag_tag::STANDARD_ONLY, $this->config->numberoftags, 'name', '', $this->page->context->id, $this->config->ctx, $this->config->rec); $this->content->text = $OUTPUT->render_from_template('core_tag/tagcloud', $tagcloud->export_for_template($OUTPUT)); return $this->content; }
/** * Prints the tag search box * * @param string $query last search string * @param int $tagcollid last selected tag collection id * @return string */ protected function search_form($query = '', $tagcollid = 0) { $searchurl = new moodle_url('/tag/search.php'); $output = '<form action="' . $searchurl . '">'; $output .= '<label class="accesshide" for="searchform_query">' . get_string('searchtags', 'tag') . '</label>'; $output .= '<input id="searchform_query" name="query" type="text" size="40" value="' . s($query) . '" />'; $tagcolls = core_tag_collection::get_collections_menu(false, true, get_string('inalltagcoll', 'tag')); if (count($tagcolls) > 1) { $output .= '<label class="accesshide" for="searchform_tc">' . get_string('selectcoll', 'tag') . '</label>'; $output .= html_writer::select($tagcolls, 'tc', $tagcollid, null, array('id' => 'searchform_tc')); } $output .= '<input name="go" type="submit" size="40" value="' . s(get_string('search', 'tag')) . '" />'; $output .= '</form>'; return $output; }
/** * Create a tag. * * @param array|stdClass $record * @return stdClass the tag record */ public function create_tag($record = null) { global $DB, $USER; $this->tagcount++; $i = $this->tagcount; $record = (array) $record; if (!isset($record['userid'])) { $record['userid'] = $USER->id; } if (!isset($record['rawname'])) { if (isset($record['name'])) { $record['rawname'] = $record['name']; } else { $record['rawname'] = 'Tag name ' . $i; } } // Attribute 'name' should be a lowercase version of 'rawname', if not set. if (!isset($record['name'])) { $record['name'] = core_text::strtolower($record['rawname']); } else { $record['name'] = core_text::strtolower($record['name']); } if (!isset($record['tagcollid'])) { $record['tagcollid'] = core_tag_collection::get_default(); } if (!isset($record['description'])) { $record['description'] = 'Tag description'; } if (!isset($record['descriptionformat'])) { $record['descriptionformat'] = FORMAT_MOODLE; } if (!isset($record['flag'])) { $record['flag'] = 0; } if (!isset($record['timemodified'])) { $record['timemodified'] = time(); } $id = $DB->insert_record('tag', $record); return $DB->get_record('tag', array('id' => $id), '*', MUST_EXIST); }
/** * 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); }
/** * 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'); }
$buttons = ''; if (has_capability('moodle/tag:manage', context_system::instance())) { $buttons .= $OUTPUT->single_button(new moodle_url('/tag/manage.php'), get_string('managetags', 'tag'), 'GET'); } if ($PAGE->user_allowed_editing()) { if ($edit != -1) { $USER->editing = $edit; } $buttons .= $OUTPUT->edit_button(clone $PAGE->url); } $PAGE->navbar->add($tagname); $PAGE->set_title(get_string('tag', 'tag') . ' - ' . $tag->get_display_name()); $PAGE->set_heading($COURSE->fullname); $PAGE->set_button($buttons); // Find all areas in this collection and their items tagged with this tag. $tagareas = core_tag_collection::get_areas($tagcollid); if ($tagareaid) { $tagareas = array_intersect_key($tagareas, array($tagareaid => 1)); } if (!$tagareaid && count($tagareas) == 1) { // Automatically set "exclusive" mode for tag collection with one tag area only. $exclusivemode = 1; } $entities = array(); foreach ($tagareas as $ta) { $entities[] = $tag->get_tag_index($ta, $exclusivemode, $fromctx, $ctx, $rec, $page); } $entities = array_filter($entities); $tagrenderer = $PAGE->get_renderer('core', 'tag'); $pagecontents = $tagrenderer->tag_index_page($tag, array_filter($entities), $tagareaid, $exclusivemode, $fromctx, $ctx, $rec, $page); echo $OUTPUT->header();
redirect(new moodle_url($manageurl, array('notice' => 'changessaved'))); } redirect($manageurl); break; case 'collmoveup': if ($tagcoll) { require_sesskey(); core_tag_collection::change_sortorder($tagcoll, -1); redirect(new moodle_url($manageurl, array('notice' => 'changessaved'))); } redirect($manageurl); break; case 'collmovedown': if ($tagcoll) { require_sesskey(); core_tag_collection::change_sortorder($tagcoll, 1); redirect(new moodle_url($manageurl, array('notice' => 'changessaved'))); } redirect($manageurl); 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':