MDL-52252 Tags: Add tags to modules (Resources and Activities)
authorNadav Kavalerchik <nadavkav@gmail.com>
Sun, 21 Feb 2016 14:10:47 +0000 (16:10 +0200)
committerMarina Glancy <marina@moodle.com>
Wed, 9 Mar 2016 06:19:47 +0000 (14:19 +0800)
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
course/lib.php
course/modedit.php
course/modlib.php
course/moodleform_mod.php
course/tests/courselib_test.php
lang/en/tag.php
lib/db/tag.php
lib/testing/generator/module_generator.php
lib/testing/tests/generator_test.php

index 436f19f..b088b1a 100644 (file)
@@ -269,6 +269,9 @@ class backup_module_structure_step extends backup_structure_step {
             'completion', 'completiongradeitemnumber', 'completionview', 'completionexpected',
             'availability', 'showdescription'));
 
+        $tags = new backup_nested_element('tags');
+        $tag = new backup_nested_element('tag', array('id'), array('name', 'rawname'));
+
         // attach format plugin structure to $module element, only one allowed
         $this->add_plugin_structure('format', $module, false);
 
@@ -279,6 +282,9 @@ class backup_module_structure_step extends backup_structure_step {
         // attach local plugin structure to $module, multiple allowed
         $this->add_plugin_structure('local', $module, true);
 
+        $module->add_child($tags);
+        $tags->add_child($tag);
+
         // Set the sources
         $concat = $DB->sql_concat("'mod_'", 'm.name');
         $module->set_source_sql("
@@ -289,6 +295,13 @@ class backup_module_structure_step extends backup_structure_step {
               JOIN {course_sections} s ON s.id = cm.section
              WHERE cm.id = ?", array(backup::VAR_MODID));
 
+        $tag->set_source_sql("SELECT t.id, t.name, t.rawname
+                                FROM {tag} t
+                                JOIN {tag_instance} ti ON ti.tagid = t.id
+                               WHERE ti.itemtype = 'course_modules'
+                                 AND ti.component = 'core'
+                                 AND ti.itemid = ?", array(backup::VAR_MODID));
+
         // Define annotations
         $module->annotate_ids('grouping', 'groupingid');
 
index caf5f07..ec316b6 100644 (file)
@@ -3584,6 +3584,8 @@ class restore_module_structure_step extends restore_structure_step {
             $paths[] = new restore_path_element('availability_field', '/module/availability_info/availability_field');
         }
 
+        $paths[] = new restore_path_element('tag', '/module/tags/tag');
+
         // Apply for 'format' plugins optional paths at module level
         $this->add_plugin_structure('format', $module);
 
@@ -3691,6 +3693,25 @@ class restore_module_structure_step extends restore_structure_step {
         }
     }
 
+    /**
+     * Fetch all the existing because tag_set() deletes them
+     * so everything must be reinserted on each call.
+     *
+     * @param stdClass $data Record data
+     */
+    protected function process_tag($data) {
+        global $CFG;
+
+        $data = (object)$data;
+
+        if (core_tag_tag::is_enabled('core', 'course_modules')) {
+            $modcontext = context::instance_by_id($this->task->get_contextid());
+            $instanceid = $this->task->get_moduleid();
+
+            core_tag_tag::add_item_tag('core', 'course_modules', $instanceid, $modcontext, $data->rawname);
+        }
+    }
+
     /**
      * Process the legacy availability table record. This table does not exist
      * in Moodle 2.7+ but we still support restore.
@@ -3759,6 +3780,20 @@ class restore_module_structure_step extends restore_structure_step {
                     array('id' => $availfield->coursemoduleid));
         }
     }
+    /**
+     * This method will be executed after the rest of the restore has been processed.
+     *
+     * Update old tag instance itemid(s).
+     */
+    protected function after_restore() {
+        global $DB;
+
+        $contextid = $this->task->get_contextid();
+        $instanceid = $this->task->get_activityid();
+        $olditemid = $this->task->get_old_activityid();
+
+        $DB->set_field('tag_instance', 'itemid', $instanceid, array('contextid' => $contextid, 'itemid' => $olditemid));
+    }
 }
 
 /**
index 4cb1e52..6afaae0 100644 (file)
@@ -1690,6 +1690,7 @@ function course_delete_module($cmid) {
 
     // Delete all tag instances associated with the instance of this module.
     core_tag_tag::delete_instances('mod_' . $modulename, null, $modcontext->id);
+    core_tag_tag::remove_all_item_tags('core', 'course_modules', $cm->id);
 
     // Delete the context.
     context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
index 65880f9..27b982b 100644 (file)
@@ -156,6 +156,7 @@ if (!empty($add)) {
     $data->completionexpected = $cm->completionexpected;
     $data->completionusegrade = is_null($cm->completiongradeitemnumber) ? 0 : 1;
     $data->showdescription    = $cm->showdescription;
+    $data->tags               = core_tag_tag::get_item_tags_array('core', 'course_modules', $cm->id);
     if (!empty($CFG->enableavailability)) {
         $data->availabilityconditionsjson = $cm->availability;
     }
index b878ca1..56814ad 100644 (file)
@@ -151,6 +151,11 @@ function add_moduleinfo($moduleinfo, $course, $mform = null) {
         $DB->set_field($moduleinfo->modulename, 'intro', $moduleinfo->intro, array('id'=>$moduleinfo->instance));
     }
 
+    // Add module tags.
+    if (core_tag_tag::is_enabled('core', 'course_modules') && isset($moduleinfo->tags)) {
+        core_tag_tag::set_item_tags('core', 'course_modules', $moduleinfo->coursemodule, $modcontext, $moduleinfo->tags);
+    }
+
     // Course_modules and course_sections each contain a reference to each other.
     // So we have to update one of them twice.
     $sectionid = course_add_cm_to_section($course, $moduleinfo->coursemodule, $moduleinfo->section);
@@ -578,6 +583,11 @@ function update_moduleinfo($cm, $moduleinfo, $course, $mform = null) {
         set_coursemodule_idnumber($moduleinfo->coursemodule, $moduleinfo->cmidnumber);
     }
 
+    // Update module tags.
+    if (core_tag_tag::is_enabled('core', 'course_modules') && isset($moduleinfo->tags)) {
+        core_tag_tag::set_item_tags('core', 'course_modules', $moduleinfo->coursemodule, $modcontext, $moduleinfo->tags);
+    }
+
     // Now that module is fully updated, also update completion data if required.
     // (this will wipe all user completion data and recalculate it)
     if ($completion->is_enabled() && !empty($moduleinfo->completionunlocked)) {
index 1f493d0..f8541a1 100644 (file)
@@ -597,6 +597,20 @@ abstract class moodleform_mod extends moodleform {
             $mform->disabledIf('completionexpected', 'completion', 'eq', COMPLETION_TRACKING_NONE);
         }
 
+        // Populate module tags.
+        $categorycontext = context_coursecat::instance($COURSE->category);
+        $coursecontext = context_course::instance($COURSE->id);
+        if (core_tag_tag::is_enabled('core', 'course_modules')) {
+            $mform->addElement('header', 'tagshdr', get_string('tags', 'tag'));
+            $mform->addElement('tags', 'tags', get_string('tags'), array('itemtype' => 'course_modules', 'component' => 'core'));
+            if ($this->_cm) {
+                $modinfo = get_fast_modinfo($COURSE);
+                $cm = $modinfo->get_cm($this->_cm->id);
+                $tags = core_tag_tag::get_item_tags_array('core', 'course_modules', $cm->id);
+                $mform->setDefault('tags', $tags);
+            }
+        }
+
         $this->standard_hidden_coursemodule_elements();
     }
 
index de74065..5692f6c 100644 (file)
@@ -1521,10 +1521,10 @@ class core_course_courselib_testcase extends advanced_testcase {
         switch ($type) {
             case 'assign':
                 // Add some tags to this assignment.
-                core_tag_tag::set_item_tags('mod_assign', 'assign', $module->id, $modcontext, array('Tag 1', 'Tag 2', 'Tag 3'));
+                core_tag_tag::set_item_tags('core', 'course_modules', $module->id, $modcontext, array('Tag 1', 'Tag 2', 'Tag 3'));
 
                 // Confirm the tag instances were added.
-                $criteria = array('component' => 'mod_assign', 'contextid' => $modcontext->id);
+                $criteria = array('component' => 'core', 'itemtype' => 'course_modules', 'contextid' => $modcontext->id);
                 $this->assertEquals(3, $DB->count_records('tag_instance', $criteria));
 
                 // Verify event assignment event has been generated.
index 552cdcc..af4bd3f 100644 (file)
@@ -116,6 +116,7 @@ $string['tagarea_blog_external'] = 'External blog posts';
 $string['tagarea_post'] = 'Blog posts';
 $string['tagarea_user'] = 'User interests';
 $string['tagarea_course'] = 'Courses';
+$string['tagarea_course_modules'] = 'Course modules';
 $string['tagareaenabled'] = 'Enabled';
 $string['tagareaname'] = 'Name';
 $string['tagareas'] = 'Tag areas';
index 074b685..80bb379 100644 (file)
@@ -80,4 +80,8 @@ $tagareas = array(
         'itemtype' => 'blog_external', // External blogs.
         'component' => 'core',
     ),
+    array(
+        'itemtype' => 'course_modules', // Course modules.
+        'component' => 'core',
+    ),
 );
index e686f6a..81e68a5 100644 (file)
@@ -248,6 +248,10 @@ abstract class testing_module_generator extends component_generator_base {
             $record->introformat = FORMAT_MOODLE;
         }
 
+        if (isset($record->tags) && !is_array($record->tags)) {
+            $record->tags = preg_split('/\s*,\s*/', trim($record->tags), -1, PREG_SPLIT_NO_EMPTY);
+        }
+
         // Before Moodle 2.6 it was possible to create a module with completion tracking when
         // it is not setup for course and/or site-wide. Display debugging message so it is
         // easier to trace an error in unittests.
index 42e07fd..0c55fab 100644 (file)
@@ -199,6 +199,10 @@ class core_test_generator_testcase extends advanced_testcase {
         $cm = get_coursemodule_from_instance('page', $page->id, $SITE->id, true);
         $this->assertEquals(3, $cm->sectionnum);
 
+        $page = $generator->create_module('page', array('course' => $SITE->id, 'tags' => 'Cat, Dog'));
+        $this->assertEquals(array('Cat', 'Dog'),
+            array_values(core_tag_tag::get_item_tags_array('core', 'course_modules', $page->cmid)));
+
         // Prepare environment to generate modules with all possible options.
 
         // Enable advanced functionality.