MDL-61363 tag: allow tagging in different context to item
This commit is contained in:
Regular → Executable
+3
-2
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="lib/db" VERSION="20171222" COMMENT="XMLDB file for core Moodle tables"
|
||||
<XMLDB PATH="lib/db" VERSION="20180222" COMMENT="XMLDB file for core Moodle tables"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
@@ -2019,6 +2019,7 @@
|
||||
<FIELD NAME="callback" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false"/>
|
||||
<FIELD NAME="callbackfile" TYPE="char" LENGTH="100" NOTNULL="false" SEQUENCE="false"/>
|
||||
<FIELD NAME="showstandard" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="multiplecontexts" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether the tag area allows tag instances to be created in multiple contexts."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
@@ -2081,7 +2082,7 @@
|
||||
<KEY NAME="contextid" TYPE="foreign" FIELDS="contextid" REFTABLE="context" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
<INDEXES>
|
||||
<INDEX NAME="taggeditem" UNIQUE="true" FIELDS="component, itemtype, itemid, tiuserid, tagid"/>
|
||||
<INDEX NAME="taggeditem" UNIQUE="true" FIELDS="component, itemtype, itemid, contextid, tiuserid, tagid"/>
|
||||
<INDEX NAME="taglookup" UNIQUE="false" FIELDS="itemtype, component, tagid, contextid"/>
|
||||
</INDEXES>
|
||||
</TABLE>
|
||||
|
||||
@@ -69,6 +69,7 @@ $tagareas = array(
|
||||
array(
|
||||
'itemtype' => 'question', // Questions.
|
||||
'component' => 'core_question',
|
||||
'multiplecontexts' => true,
|
||||
),
|
||||
array(
|
||||
'itemtype' => 'post', // Blog posts.
|
||||
|
||||
+39
-1
@@ -1974,7 +1974,6 @@ function xmldb_main_upgrade($oldversion) {
|
||||
}
|
||||
|
||||
if ($oldversion < 2018022800.01) {
|
||||
|
||||
// Fix old block configurations that use the deprecated (and now removed) object class.
|
||||
upgrade_fix_block_instance_configuration();
|
||||
|
||||
@@ -1982,5 +1981,44 @@ function xmldb_main_upgrade($oldversion) {
|
||||
upgrade_main_savepoint(true, 2018022800.01);
|
||||
}
|
||||
|
||||
if ($oldversion < 2018022800.02) {
|
||||
// Define index taggeditem (unique) to be dropped form tag_instance.
|
||||
$table = new xmldb_table('tag_instance');
|
||||
$index = new xmldb_index('taggeditem', XMLDB_INDEX_UNIQUE, array('component',
|
||||
'itemtype', 'itemid', 'tiuserid', 'tagid'));
|
||||
|
||||
// Conditionally launch drop index taggeditem.
|
||||
if ($dbman->index_exists($table, $index)) {
|
||||
$dbman->drop_index($table, $index);
|
||||
}
|
||||
|
||||
$index = new xmldb_index('taggeditem', XMLDB_INDEX_UNIQUE, array('component',
|
||||
'itemtype', 'itemid', 'contextid', 'tiuserid', 'tagid'));
|
||||
|
||||
// Conditionally launch add index taggeditem.
|
||||
if (!$dbman->index_exists($table, $index)) {
|
||||
$dbman->add_index($table, $index);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2018022800.02);
|
||||
}
|
||||
|
||||
if ($oldversion < 2018022800.03) {
|
||||
|
||||
// Define field multiplecontexts to be added to tag_area.
|
||||
$table = new xmldb_table('tag_area');
|
||||
$field = new xmldb_field('multiplecontexts', XMLDB_TYPE_INTEGER, '1', null,
|
||||
XMLDB_NOTNULL, null, '0', 'showstandard');
|
||||
|
||||
// Conditionally launch add field multiplecontexts.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2018022800.03);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+33
-2
@@ -122,6 +122,32 @@ class core_tag_area {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the tag area allows items to be tagged in multiple different contexts.
|
||||
*
|
||||
* If true then it indicates that not all tag instance contexts must match the
|
||||
* context of the item they are tagging. If false then all tag instance should
|
||||
* match the context of the item they are tagging.
|
||||
*
|
||||
* Example use case for multi-context tagging:
|
||||
* A question that exists in a course category context may be used by multiple
|
||||
* child courses. The question tag area can allow tag instances to be created in
|
||||
* multiple contexts which allows the tag API to tag the question at the course
|
||||
* category context and then seperately in each of the child course contexts.
|
||||
*
|
||||
* @param string $component component responsible for tagging
|
||||
* @param string $itemtype what is being tagged, for example, 'post', 'course', 'user', etc.
|
||||
* @return bool
|
||||
*/
|
||||
public static function allows_tagging_in_multiple_contexts($component, $itemtype) {
|
||||
$itemtypes = self::get_areas();
|
||||
if (isset($itemtypes[$itemtype][$component])) {
|
||||
$config = $itemtypes[$itemtype][$component];
|
||||
return isset($config->multiplecontexts) ? $config->multiplecontexts : false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the tag collection that should be used for storing tags of this itemtype
|
||||
*
|
||||
@@ -217,7 +243,8 @@ class core_tag_area {
|
||||
'tagcollid' => $record->tagcollid,
|
||||
'callback' => $record->callback,
|
||||
'callbackfile' => $record->callbackfile,
|
||||
'showstandard' => isset($record->showstandard) ? $record->showstandard : core_tag_tag::BOTH_STANDARD_AND_NOT));
|
||||
'showstandard' => isset($record->showstandard) ? $record->showstandard : core_tag_tag::BOTH_STANDARD_AND_NOT,
|
||||
'multiplecontexts' => isset($record->multiplecontexts) ? $record->multiplecontexts : 0));
|
||||
|
||||
// Reset cache.
|
||||
cache::make('core', 'tags')->delete('tag_area');
|
||||
@@ -233,7 +260,8 @@ class core_tag_area {
|
||||
global $DB;
|
||||
$data = array_intersect_key((array)$data,
|
||||
array('enabled' => 1, 'tagcollid' => 1,
|
||||
'callback' => 1, 'callbackfile' => 1, 'showstandard' => 1));
|
||||
'callback' => 1, 'callbackfile' => 1, 'showstandard' => 1,
|
||||
'multiplecontexts' => 1));
|
||||
foreach ($data as $key => $value) {
|
||||
if ($existing->$key == $value) {
|
||||
unset($data[$key]);
|
||||
@@ -310,6 +338,9 @@ class core_tag_area {
|
||||
if (!isset($record->callbackfile)) {
|
||||
$record->callbackfile = null;
|
||||
}
|
||||
if (!isset($record->multiplecontexts)) {
|
||||
$record->multiplecontexts = false;
|
||||
}
|
||||
$itemtypes[$record->itemtype . ':' . $record->component] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
+45
-3
@@ -602,7 +602,7 @@ class core_tag_tag {
|
||||
global $DB;
|
||||
$this->ensure_fields_exist(array('name', 'rawname'), 'add_instance');
|
||||
|
||||
$taginstance = new StdClass;
|
||||
$taginstance = new stdClass;
|
||||
$taginstance->tagid = $this->id;
|
||||
$taginstance->component = $component ? $component : '';
|
||||
$taginstance->itemid = $itemid;
|
||||
@@ -773,12 +773,35 @@ class core_tag_tag {
|
||||
$tagobjects = array();
|
||||
}
|
||||
|
||||
$allowmultiplecontexts = core_tag_area::allows_tagging_in_multiple_contexts($component, $itemtype);
|
||||
$currenttags = static::get_item_tags($component, $itemtype, $itemid, self::BOTH_STANDARD_AND_NOT, $tiuserid);
|
||||
$taginstanceidstomovecontext = [];
|
||||
|
||||
// For data coherence reasons, it's better to remove deleted tags
|
||||
// before adding new data: ordering could be duplicated.
|
||||
foreach ($currenttags as $currenttag) {
|
||||
if (!array_key_exists($currenttag->name, $tagobjects)) {
|
||||
$hasbeenrequested = array_key_exists($currenttag->name, $tagobjects);
|
||||
$issamecontext = $currenttag->taginstancecontextid == $context->id;
|
||||
|
||||
if ($allowmultiplecontexts) {
|
||||
// If the tag area allows multiple contexts then we should only be
|
||||
// managing tags in the given $context. All other tags can be ignored.
|
||||
$shoulddelete = $issamecontext && !$hasbeenrequested;
|
||||
} else {
|
||||
// If the tag area only allows tag instances in a single context then
|
||||
// all tags that aren't in the requested tags should be deleted, regardless
|
||||
// of their context, if they are not part of the new set of tags.
|
||||
$shoulddelete = !$hasbeenrequested;
|
||||
// If the tag instance isn't in the correct context (legacy data)
|
||||
// then we should take this opportunity to update it with the correct
|
||||
// context id.
|
||||
if (!$shoulddelete && !$issamecontext) {
|
||||
$currenttag->taginstancecontextid = $context->id;
|
||||
$taginstanceidstomovecontext[] = $currenttag->taginstanceid;
|
||||
}
|
||||
}
|
||||
|
||||
if ($shoulddelete) {
|
||||
$taginstance = (object)array('id' => $currenttag->taginstanceid,
|
||||
'itemtype' => $itemtype, 'itemid' => $itemid,
|
||||
'contextid' => $currenttag->taginstancecontextid, 'tiuserid' => $tiuserid);
|
||||
@@ -786,11 +809,30 @@ class core_tag_tag {
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($taginstanceidstomovecontext)) {
|
||||
static::change_instances_context($taginstanceidstomovecontext, $context);
|
||||
}
|
||||
|
||||
$ordering = -1;
|
||||
foreach ($tagobjects as $name => $tag) {
|
||||
$ordering++;
|
||||
foreach ($currenttags as $currenttag) {
|
||||
if (strval($currenttag->name) === strval($name)) {
|
||||
$namesmatch = strval($currenttag->name) === strval($name);
|
||||
|
||||
if ($allowmultiplecontexts) {
|
||||
// If the tag area allows multiple contexts then we should only
|
||||
// skip adding a new instance if the existing one is in the correct
|
||||
// context.
|
||||
$contextsmatch = $currenttag->taginstancecontextid == $context->id;
|
||||
$shouldskipinstance = $namesmatch && $contextsmatch;
|
||||
} else {
|
||||
// The existing behaviour for single context tag areas is to
|
||||
// skip adding a new instance regardless of whether the existing
|
||||
// instance is in the same context as the provided $context.
|
||||
$shouldskipinstance = $namesmatch;
|
||||
}
|
||||
|
||||
if ($shouldskipinstance) {
|
||||
if ($currenttag->ordering != $ordering) {
|
||||
$currenttag->update_instance_ordering($currenttag->taginstanceid, $ordering);
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2018022800.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2018022800.03; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user