MDL-50851 course: use new tag API
authorMarina Glancy <marina@moodle.com>
Sat, 5 Sep 2015 15:05:45 +0000 (23:05 +0800)
committerMarina Glancy <marina@moodle.com>
Sun, 10 Jan 2016 07:25:47 +0000 (15:25 +0800)
backup/moodle2/restore_stepslib.php
course/edit.php
course/edit_form.php
course/lib.php
course/renderer.php
course/tags.php
course/tags_form.php
course/tests/courselib_test.php
course/tests/externallib_test.php
lib/coursecatlib.php
lib/moodlelib.php

index a41292d..88e118e 100644 (file)
@@ -1778,22 +1778,8 @@ class restore_course_structure_step extends restore_structure_step {
 
         $data = (object)$data;
 
-        if (!empty($CFG->usetags)) { // if enabled in server
-            // TODO: This is highly inneficient. Each time we add one tag
-            // we fetch all the existing because tag_set() deletes them
-            // so everything must be reinserted on each call
-            $tags = array();
-            $existingtags = tag_get_tags('course', $this->get_courseid());
-            // Re-add all the existitng tags
-            foreach ($existingtags as $existingtag) {
-                $tags[] = $existingtag->rawname;
-            }
-            // Add the one being restored
-            $tags[] = $data->rawname;
-            // Send all the tags back to the course
-            tag_set('course', $this->get_courseid(), $tags, 'core',
-                context_course::instance($this->get_courseid())->id);
-        }
+        core_tag_tag::add_item_tag('core', 'course', $this->get_courseid(),
+                context_course::instance($this->get_courseid()), $data->rawname);
     }
 
     public function process_allowed_module($data) {
index 0189fae..d79c0d6 100644 (file)
@@ -123,10 +123,7 @@ if (!empty($course)) {
     }
 
     // Populate course tags.
-    if (!empty($CFG->usetags)) {
-        include_once($CFG->dirroot.'/tag/lib.php');
-        $course->tags = tag_get_tags_array('course', $course->id);
-    }
+    $course->tags = core_tag_tag::get_item_tags_array('core', 'course', $course->id);
 
 } else {
     // Editor should respect category context if course context is not set.
index 94d260c..7c9f43e 100644 (file)
@@ -304,11 +304,12 @@ class course_edit_form extends moodleform {
             }
         }
 
-        if (!empty($CFG->usetags) &&
+        if (core_tag_tag::is_enabled('core', 'course') &&
                 ((empty($course->id) && guess_if_creator_will_have_course_capability('moodle/course:tag', $categorycontext))
                 || (!empty($course->id) && has_capability('moodle/course:tag', $coursecontext)))) {
             $mform->addElement('header', 'tagshdr', get_string('tags', 'tag'));
-            $mform->addElement('tags', 'tags', get_string('tags'));
+            $mform->addElement('tags', 'tags', get_string('tags'),
+                    array('itemtype' => 'course', 'component' => 'core'));
         }
 
         // When two elements we need a group.
index 5412f24..0c2acd3 100644 (file)
@@ -1716,7 +1716,7 @@ function course_delete_module($cmid) {
                                                             'criteriatype' => COMPLETION_CRITERIA_TYPE_ACTIVITY));
 
     // Delete all tag instances associated with the instance of this module.
-    core_tag::delete_instances('mod_' . $modulename, null, $modcontext->id);
+    core_tag_tag::delete_instances('mod_' . $modulename, null, $modcontext->id);
 
     // Delete the context.
     context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
@@ -2582,7 +2582,6 @@ function course_overviewfiles_options($course) {
  */
 function create_course($data, $editoroptions = NULL) {
     global $DB, $CFG;
-    require_once($CFG->dirroot.'/tag/lib.php');
 
     //check the categoryid - must be given for all new courses
     $category = $DB->get_record('course_categories', array('id'=>$data->category), '*', MUST_EXIST);
@@ -2668,8 +2667,8 @@ function create_course($data, $editoroptions = NULL) {
     enrol_course_updated(true, $course, $data);
 
     // Update course tags.
-    if ($CFG->usetags && isset($data->tags)) {
-        tag_set('course', $course->id, $data->tags, 'core', context_course::instance($course->id)->id);
+    if (isset($data->tags)) {
+        core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags);
     }
 
     return $course;
@@ -2687,7 +2686,6 @@ function create_course($data, $editoroptions = NULL) {
  */
 function update_course($data, $editoroptions = NULL) {
     global $DB, $CFG;
-    require_once($CFG->dirroot.'/tag/lib.php');
 
     $data->timemodified = time();
 
@@ -2775,8 +2773,8 @@ function update_course($data, $editoroptions = NULL) {
     enrol_course_updated(false, $course, $data);
 
     // Update course tags.
-    if ($CFG->usetags && isset($data->tags)) {
-        tag_set('course', $course->id, $data->tags, 'core', context_course::instance($course->id)->id);
+    if (isset($data->tags)) {
+        core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags);
     }
 
     // Trigger a course updated event.
@@ -3828,3 +3826,36 @@ function course_view($context, $sectionnumber = 0) {
     $event = \core\event\course_viewed::create($eventdata);
     $event->trigger();
 }
+
+/**
+ * Returns courses tagged with a specified tag.
+ *
+ * @param core_tag_tag $tag
+ * @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 \core_tag\output\tagindex
+ */
+function course_get_tagged_courses($tag, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0) {
+    global $CFG, $PAGE;
+    require_once($CFG->libdir . '/coursecatlib.php');
+
+    $perpage = $exclusivemode ? $CFG->coursesperpage : 5;
+    $displayoptions = array(
+        'limit' => $perpage,
+        'offset' => $page * $perpage,
+        'viewmoreurl' => null,
+    );
+
+    $courserenderer = $PAGE->get_renderer('core', 'course');
+    $totalcount = coursecat::search_courses_count(array('tagid' => $tag->id, 'ctx' => $ctx, 'rec' => $rec));
+    $content = $courserenderer->tagged_courses($tag->id, $exclusivemode, $ctx, $rec, $displayoptions);
+    $totalpages = ceil($totalcount / $perpage);
+
+    return new core_tag\output\tagindex($tag, 'core', 'course', $content,
+            $exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
+}
index ec26762..b71d488 100644 (file)
@@ -1896,29 +1896,52 @@ class core_course_renderer extends plugin_renderer_base {
      * Renders html to print list of courses tagged with particular tag
      *
      * @param int $tagid id of the tag
+     * @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 array $displayoptions
      * @return string empty string if no courses are marked with this tag or rendered list of courses
      */
-    public function tagged_courses($tagid) {
+    public function tagged_courses($tagid, $exclusivemode = true, $ctx = 0, $rec = true, $displayoptions = null) {
         global $CFG;
-        require_once($CFG->libdir. '/coursecatlib.php');
-        $displayoptions = array('limit' => $CFG->coursesperpage);
-        $displayoptions['viewmoreurl'] = new moodle_url('/course/search.php',
-                array('tagid' => $tagid, 'page' => 1, 'perpage' => $CFG->coursesperpage));
-        $displayoptions['viewmoretext'] = new lang_string('findmorecourses');
+        require_once($CFG->libdir . '/coursecatlib.php');
+        if (empty($displayoptions)) {
+            $displayoptions = array();
+        }
+        $showcategories = coursecat::count_all() > 1;
+        $displayoptions += array('limit' => $CFG->coursesperpage, 'offset' => 0);
         $chelper = new coursecat_helper();
-        $searchcriteria = array('tagid' => $tagid);
-        $chelper->set_show_courses(self::COURSECAT_SHOW_COURSES_EXPANDED_WITH_CAT)->
-                set_search_criteria(array('tagid' => $tagid))->
+        $searchcriteria = array('tagid' => $tagid, 'ctx' => $ctx, 'rec' => $rec);
+        $chelper->set_show_courses($showcategories ? self::COURSECAT_SHOW_COURSES_EXPANDED_WITH_CAT :
+                    self::COURSECAT_SHOW_COURSES_EXPANDED)->
+                set_search_criteria($searchcriteria)->
                 set_courses_display_options($displayoptions)->
                 set_attributes(array('class' => 'course-search-result course-search-result-tagid'));
                 // (we set the same css class as in search results by tagid)
-        $courses = coursecat::search_courses($searchcriteria, $chelper->get_courses_display_options());
-        $totalcount = coursecat::search_courses_count($searchcriteria);
-        $content = $this->coursecat_courses($chelper, $courses, $totalcount);
-        if ($totalcount) {
-            require_once $CFG->dirroot.'/tag/lib.php';
-            $heading = get_string('courses') . ' ' . get_string('taggedwith', 'tag', tag_get_name($tagid)) .': '. $totalcount;
-            return $this->heading($heading, 3). $content;
+        if ($totalcount = coursecat::search_courses_count($searchcriteria)) {
+            $courses = coursecat::search_courses($searchcriteria, $chelper->get_courses_display_options());
+            if ($exclusivemode) {
+                return $this->coursecat_courses($chelper, $courses, $totalcount);
+            } else {
+                $tagfeed = new core_tag\output\tagfeed();
+                $img = $this->output->pix_icon('i/course', '');
+                foreach ($courses as $course) {
+                    $url = course_get_url($course);
+                    $imgwithlink = html_writer::link($url, $img);
+                    $coursename = html_writer::link($url, $course->get_formatted_name());
+                    $details = '';
+                    if ($showcategories && ($cat = coursecat::get($course->category, IGNORE_MISSING))) {
+                        $details = get_string('category').': '.
+                                html_writer::link(new moodle_url('/course/index.php', array('categoryid' => $cat->id)),
+                                        $cat->get_formatted_name(), array('class' => $cat->visible ? '' : 'dimmed'));
+                    }
+                    $tagfeed->add($imgwithlink, $coursename, $details);
+                }
+                return $this->output->render_from_template('core_tag/tagfeed', $tagfeed->export_for_template($this->output));
+            }
         }
         return '';
     }
index 8e81fb1..1c7ad66 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 require_once("../config.php");
-require_once($CFG->dirroot . '/tag/lib.php');
 require_once($CFG->dirroot . '/course/tags_form.php');
 
 $id = required_param('id', PARAM_INT); // Course id.
@@ -38,7 +37,7 @@ if (!$course->visible and !has_capability('moodle/course:viewhiddencourses', $co
     print_error('coursehidden', '', $CFG->wwwroot .'/');
 }
 require_capability('moodle/course:tag', $context);
-if (empty($CFG->usetags)) {
+if (!core_tag_tag::is_enabled('core', 'course')) {
     print_error('tagsaredisabled', 'tag');
 }
 
@@ -49,14 +48,14 @@ $PAGE->set_title(get_string('coursetags', 'tag'));
 $PAGE->set_heading($course->fullname);
 
 $form = new coursetags_form();
-$data = array('id' => $course->id, 'tags' => tag_get_tags_array('course', $course->id));
+$data = array('id' => $course->id, 'tags' => core_tag_tag::get_item_tags_array('core', 'course', $course->id));
 $form->set_data($data);
 
 $redirecturl = $returnurl ? new moodle_url($returnurl) : course_get_url($course);
 if ($form->is_cancelled()) {
     redirect($redirecturl);
 } else if ($data = $form->get_data()) {
-    tag_set('course', $course->id, $data->tags, 'core', context_course::instance($course->id)->id);
+    core_tag_tag::set_item_tags('core', 'course', $course->id, context_course::instance($course->id), $data->tags);
     redirect($redirecturl);
 }
 
index 08cacc0..fc54c03 100644 (file)
@@ -41,7 +41,8 @@ class coursetags_form extends moodleform {
     public function definition() {
         $mform    = $this->_form;
 
-        $mform->addElement('tags', 'tags', get_string('tags'));
+        $mform->addElement('tags', 'tags', get_string('tags'),
+                    array('itemtype' => 'course', 'component' => 'core'));
 
         $mform->addElement('hidden', 'id', null);
         $mform->setType('id', PARAM_INT);
index 421b1e4..de74065 100644 (file)
@@ -29,7 +29,6 @@ global $CFG;
 require_once($CFG->dirroot . '/course/lib.php');
 require_once($CFG->dirroot . '/course/tests/fixtures/course_capability_assignment.php');
 require_once($CFG->dirroot . '/enrol/imsenterprise/tests/imsenterprise_test.php');
-require_once($CFG->dirroot . '/tag/lib.php');
 
 class core_course_courselib_testcase extends advanced_testcase {
 
@@ -1501,6 +1500,7 @@ class core_course_courselib_testcase extends advanced_testcase {
      */
     public function test_course_delete_module($type, $options) {
         global $DB;
+
         $this->resetAfterTest(true);
         $this->setAdminUser();
 
@@ -1521,7 +1521,7 @@ class core_course_courselib_testcase extends advanced_testcase {
         switch ($type) {
             case 'assign':
                 // Add some tags to this assignment.
-                tag_set('assign', $module->id, array('Tag 1', 'Tag 2', 'Tag 3'), 'mod_assign', $modcontext->id);
+                core_tag_tag::set_item_tags('mod_assign', 'assign', $module->id, $modcontext, array('Tag 1', 'Tag 2', 'Tag 3'));
 
                 // Confirm the tag instances were added.
                 $criteria = array('component' => 'mod_assign', 'contextid' => $modcontext->id);
index c5a6464..10a84ba 100644 (file)
@@ -605,8 +605,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
      */
     public function test_search_courses () {
 
-        global $DB, $CFG;
-        require_once($CFG->dirroot . '/tag/lib.php');
+        global $DB;
 
         $this->resetAfterTest(true);
         $this->setAdminUser();
@@ -636,8 +635,10 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         // Enable coursetag option.
         set_config('block_tags_showcoursetags', true);
         // Add tag 'TAG-LABEL ON SECOND COURSE' to Course2.
-        tag_set('course', $course2->id, array('TAG-LABEL ON SECOND COURSE'), 'core', context_course::instance($course2->id)->id);
-        $taginstance = $DB->get_record('tag_instance', array('itemtype' => 'course', 'itemid' => $course2->id), '*', MUST_EXIST);
+        core_tag_tag::set_item_tags('core', 'course', $course2->id, context_course::instance($course2->id),
+                array('TAG-LABEL ON SECOND COURSE'));
+        $taginstance = $DB->get_record('tag_instance',
+                array('itemtype' => 'course', 'itemid' => $course2->id), '*', MUST_EXIST);
         // Search by tagid.
         $results = core_course_external::search_courses('tagid', $taginstance->tagid);
         $results = external_api::clean_returnvalue(core_course_external::search_courses_returns(), $results);
index df83db6..fc8811f 100644 (file)
@@ -1339,8 +1339,27 @@ class coursecat implements renderable, cacheable_object, IteratorAggregate {
             } else if (!empty($search['tagid'])) {
                 // Search courses that are tagged with the specified tag.
                 $where = "c.id IN (SELECT t.itemid ".
-                        "FROM {tag_instance} t WHERE t.tagid = :tagid AND t.itemtype = :itemtype)";
-                $params = array('tagid' => $search['tagid'], 'itemtype' => 'course');
+                        "FROM {tag_instance} t WHERE t.tagid = :tagid AND t.itemtype = :itemtype AND t.component = :component)";
+                $params = array('tagid' => $search['tagid'], 'itemtype' => 'course', 'component' => 'core');
+                if (!empty($search['ctx'])) {
+                    $rec = isset($search['rec']) ? $search['rec'] : true;
+                    $parentcontext = context::instance_by_id($search['ctx']);
+                    if ($parentcontext->contextlevel == CONTEXT_SYSTEM && $rec) {
+                        // Parent context is system context and recursive is set to yes.
+                        // Nothing to filter - all courses fall into this condition.
+                    } else if ($rec) {
+                        // Filter all courses in the parent context at any level.
+                        $where .= ' AND ctx.path LIKE :contextpath';
+                        $params['contextpath'] = $parentcontext->path . '%';
+                    } else if ($parentcontext->contextlevel == CONTEXT_COURSECAT) {
+                        // All courses in the given course category.
+                        $where .= ' AND c.category = :category';
+                        $params['category'] = $parentcontext->instanceid;
+                    } else {
+                        // No courses will satisfy the context criterion, do not bother searching.
+                        $where = '1=0';
+                    }
+                }
             } else {
                 debugging('No criteria is specified while searching courses', DEBUG_DEVELOPER);
                 return array();
index e9598eb..9b0b8f9 100644 (file)
@@ -4735,7 +4735,6 @@ function remove_course_contents($courseid, $showfeedback = true, array $options
     require_once($CFG->libdir.'/questionlib.php');
     require_once($CFG->libdir.'/gradelib.php');
     require_once($CFG->dirroot.'/group/lib.php');
-    require_once($CFG->dirroot.'/tag/lib.php');
     require_once($CFG->dirroot.'/comment/lib.php');
     require_once($CFG->dirroot.'/rating/lib.php');
     require_once($CFG->dirroot.'/notes/lib.php');
@@ -4910,7 +4909,7 @@ function remove_course_contents($courseid, $showfeedback = true, array $options
     $rm->delete_ratings($delopt);
 
     // Delete course tags.
-    tag_set('course', $course->id, array(), 'core', $coursecontext->id);
+    core_tag_tag::remove_all_item_tags('core', 'course', $course->id);
 
     // Delete calendar events.
     $DB->delete_records('event', array('courseid' => $course->id));