MDL-25742 mod_wiki: show wiki pages tagged with a tag

This commit is contained in:
Marina Glancy
2016-04-13 07:57:58 +08:00
parent aca13ea2b6
commit 92c90b96ce
6 changed files with 224 additions and 9 deletions
+2
View File
@@ -29,5 +29,7 @@ $tagareas = array(
array(
'itemtype' => 'wiki_pages',
'component' => 'mod_wiki',
'callback' => 'mod_wiki_get_tagged_pages',
'callbackfile' => '/mod/wiki/locallib.php',
),
);
+115
View File
@@ -1734,3 +1734,118 @@ function wiki_get_subwiki_by_group_and_user_with_validation($wiki, $groupid, $us
return $subwiki;
}
/**
* Returns wiki pages tagged with a specified tag.
*
* This is a callback used by the tag area mod_wiki/wiki_pages to search for wiki pages
* tagged with a specific 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 mod_wiki_get_tagged_pages($tag, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0) {
global $OUTPUT;
$perpage = $exclusivemode ? 20 : 5;
// Build the SQL query.
$ctxselect = context_helper::get_preload_record_columns_sql('ctx');
$query = "SELECT wp.id, wp.title, ws.userid, ws.wikiid, ws.id AS subwikiid, ws.groupid, w.wikimode,
cm.id AS cmid, c.id AS courseid, c.shortname, c.fullname, $ctxselect
FROM {wiki_pages} wp
JOIN {wiki_subwikis} ws ON wp.subwikiid = ws.id
JOIN {wiki} w ON w.id = ws.wikiid
JOIN {modules} m ON m.name='wiki'
JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = w.id
JOIN {tag_instance} tt ON wp.id = tt.itemid
JOIN {course} c ON cm.course = c.id
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :coursemodulecontextlevel
WHERE tt.itemtype = :itemtype AND tt.tagid = :tagid AND tt.component = :component
AND wp.id %ITEMFILTER% AND c.id %COURSEFILTER%";
$params = array('itemtype' => 'wiki_pages', 'tagid' => $tag->id, 'component' => 'mod_wiki',
'coursemodulecontextlevel' => CONTEXT_MODULE);
if ($ctx) {
$context = $ctx ? context::instance_by_id($ctx) : context_system::instance();
$query .= $rec ? ' AND (ctx.id = :contextid OR ctx.path LIKE :path)' : ' AND ctx.id = :contextid';
$params['contextid'] = $context->id;
$params['path'] = $context->path.'/%';
}
$query .= " ORDER BY ";
if ($fromctx) {
// In order-clause specify that modules from inside "fromctx" context should be returned first.
$fromcontext = context::instance_by_id($fromctx);
$query .= ' (CASE WHEN ctx.id = :fromcontextid OR ctx.path LIKE :frompath THEN 0 ELSE 1 END),';
$params['fromcontextid'] = $fromcontext->id;
$params['frompath'] = $fromcontext->path.'/%';
}
$query .= ' c.sortorder, cm.id, wp.id';
$totalpages = $page + 1;
// Use core_tag_index_builder to build and filter the list of items.
$builder = new core_tag_index_builder('mod_wiki', 'wiki_pages', $query, $params, $page * $perpage, $perpage + 1);
while ($item = $builder->has_item_that_needs_access_check()) {
context_helper::preload_from_record($item);
$courseid = $item->courseid;
if (!$builder->can_access_course($courseid)) {
$builder->set_accessible($item, false);
continue;
}
$modinfo = get_fast_modinfo($builder->get_course($courseid));
// Set accessibility of this item and all other items in the same course.
$builder->walk(function ($taggeditem) use ($courseid, $modinfo, $builder) {
if ($taggeditem->courseid == $courseid) {
$accessible = false;
if (($cm = $modinfo->get_cm($taggeditem->cmid)) && $cm->uservisible) {
$subwiki = (object)array('id' => $taggeditem->subwikiid, 'groupid' => $taggeditem->groupid,
'userid' => $taggeditem->groupid, 'wikiid' => $taggeditem->wikiid);
$wiki = (object)array('id' => $taggeditem->wikiid, 'wikimode' => $taggeditem->wikimode,
'course' => $cm->course);
$accessible = wiki_user_can_view($subwiki, $wiki);
}
$builder->set_accessible($taggeditem, $accessible);
}
});
}
$items = $builder->get_items();
if (count($items) > $perpage) {
$totalpages = $page + 2; // We don't need exact page count, just indicate that the next page exists.
array_pop($items);
}
// Build the display contents.
if ($items) {
$tagfeed = new core_tag\output\tagfeed();
foreach ($items as $item) {
context_helper::preload_from_record($item);
$modinfo = get_fast_modinfo($item->courseid);
$cm = $modinfo->get_cm($item->cmid);
$pageurl = new moodle_url('/mod/wiki/view.php', array('pageid' => $item->id));
$pagename = format_string($item->title, true, array('context' => context_module::instance($item->cmid)));
$pagename = html_writer::link($pageurl, $pagename);
$courseurl = course_get_url($item->courseid, $cm->sectionnum);
$cmname = html_writer::link($cm->url, $cm->get_formatted_name());
$coursename = format_string($item->fullname, true, array('context' => context_course::instance($item->courseid)));
$coursename = html_writer::link($courseurl, $coursename);
$icon = html_writer::link($pageurl, html_writer::empty_tag('img', array('src' => $cm->get_icon_url())));
$tagfeed->add($icon, $pagename, $cmname.'<br>'.$coursename);
}
$content = $OUTPUT->render_from_template('core_tag/tagfeed',
$tagfeed->export_for_template($OUTPUT));
return new core_tag\output\tagindex($tag, 'mod_wiki', 'wiki_pages', $content,
$exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
}
}
+14 -6
View File
@@ -110,14 +110,22 @@ class mod_wiki_generator extends testing_module_generator {
}
}
if ($wikipage = wiki_get_page_by_title($record['subwikiid'], $record['title'])) {
$rv = wiki_save_page($wikipage, $record['content'], $USER->id);
return $rv['page'];
$wikipage = wiki_get_page_by_title($record['subwikiid'], $record['title']);
if (!$wikipage) {
$pageid = wiki_create_page($record['subwikiid'], $record['title'], $record['format'], $USER->id);
$wikipage = wiki_get_page($pageid);
}
$pageid = wiki_create_page($record['subwikiid'], $record['title'], $record['format'], $USER->id);
$wikipage = wiki_get_page($pageid);
$rv = wiki_save_page($wikipage, $record['content'], $USER->id);
if (array_key_exists('tags', $record)) {
$tags = is_array($record['tags']) ? $record['tags'] : preg_split('/,/', $record['tags']);
if (empty($wiki->cmid)) {
$cm = get_coursemodule_from_instance('wiki', $wiki->id, isset($wiki->course) ? $wiki->course : 0);
$wiki->cmid = $cm->id;
}
core_tag_tag::set_item_tags('mod_wiki', 'wiki_pages', $wikipage->id,
context_module::instance($wiki->cmid), $tags);
}
return $rv['page'];
}
}
+8 -2
View File
@@ -64,16 +64,22 @@ class mod_wiki_generator_testcase extends advanced_testcase {
$page1 = $wikigenerator->create_first_page($wiki);
$page2 = $wikigenerator->create_content($wiki);
$page3 = $wikigenerator->create_content($wiki, array('title' => 'Custom title'));
$page3 = $wikigenerator->create_content($wiki, array('title' => 'Custom title', 'tags' => array('Cats', 'mice')));
unset($wiki->cmid);
$page4 = $wikigenerator->create_content($wiki, array('tags' => 'Cats, dogs'));
$subwikis = $DB->get_records('wiki_subwikis', array('wikiid' => $wiki->id), 'id');
$this->assertEquals(1, count($subwikis));
$subwikiid = key($subwikis);
$records = $DB->get_records('wiki_pages', array('subwikiid' => $subwikiid), 'id');
$this->assertEquals(3, count($records));
$this->assertEquals(4, count($records));
$this->assertEquals($page1->id, $records[$page1->id]->id);
$this->assertEquals($page2->id, $records[$page2->id]->id);
$this->assertEquals($page3->id, $records[$page3->id]->id);
$this->assertEquals('Custom title', $records[$page3->id]->title);
$this->assertEquals(array('Cats', 'mice'),
array_values(core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page3->id)));
$this->assertEquals(array('Cats', 'dogs'),
array_values(core_tag_tag::get_item_tags_array('mod_wiki', 'wiki_pages', $page4->id)));
}
public function test_create_content_individual() {
+84
View File
@@ -654,4 +654,88 @@ class mod_wiki_lib_testcase extends advanced_testcase {
$result = wiki_get_visible_subwikis($wikisepind);
$this->assertEquals($expectedsubwikis, $result, '', 0, 10, true);
}
public function test_mod_wiki_get_tagged_pages() {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
// Setup test data.
$wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
$course3 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$course1 = $this->getDataGenerator()->create_course();
$wiki1 = $this->getDataGenerator()->create_module('wiki', array('course' => $course1->id));
$wiki2 = $this->getDataGenerator()->create_module('wiki', array('course' => $course2->id));
$wiki3 = $this->getDataGenerator()->create_module('wiki', array('course' => $course3->id));
$page11 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats', 'Dogs')));
$page12 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats', 'mice')));
$page13 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats')));
$page14 = $wikigenerator->create_content($wiki1);
$page15 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats')));
$page21 = $wikigenerator->create_content($wiki2, array('tags' => array('Cats')));
$page22 = $wikigenerator->create_content($wiki2, array('tags' => array('Cats', 'Dogs')));
$page23 = $wikigenerator->create_content($wiki2, array('tags' => array('mice', 'Cats')));
$page31 = $wikigenerator->create_content($wiki3, array('tags' => array('mice', 'Cats')));
$tag = core_tag_tag::get_by_name(0, 'Cats');
// Admin can see everything.
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */0);
$this->assertRegExp('/'.$page11->title.'/', $res->content);
$this->assertRegExp('/'.$page12->title.'/', $res->content);
$this->assertRegExp('/'.$page13->title.'/', $res->content);
$this->assertNotRegExp('/'.$page14->title.'/', $res->content);
$this->assertRegExp('/'.$page15->title.'/', $res->content);
$this->assertRegExp('/'.$page21->title.'/', $res->content);
$this->assertNotRegExp('/'.$page22->title.'/', $res->content);
$this->assertNotRegExp('/'.$page23->title.'/', $res->content);
$this->assertNotRegExp('/'.$page31->title.'/', $res->content);
$this->assertEmpty($res->prevpageurl);
$this->assertNotEmpty($res->nextpageurl);
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */1);
$this->assertNotRegExp('/'.$page11->title.'/', $res->content);
$this->assertNotRegExp('/'.$page12->title.'/', $res->content);
$this->assertNotRegExp('/'.$page13->title.'/', $res->content);
$this->assertNotRegExp('/'.$page14->title.'/', $res->content);
$this->assertNotRegExp('/'.$page15->title.'/', $res->content);
$this->assertNotRegExp('/'.$page21->title.'/', $res->content);
$this->assertRegExp('/'.$page22->title.'/', $res->content);
$this->assertRegExp('/'.$page23->title.'/', $res->content);
$this->assertRegExp('/'.$page31->title.'/', $res->content);
$this->assertNotEmpty($res->prevpageurl);
$this->assertEmpty($res->nextpageurl);
// Create and enrol a user.
$student = self::getDataGenerator()->create_user();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual');
$this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual');
$this->setUser($student);
core_tag_index_builder::reset_caches();
// User can not see pages in course 3 because he is not enrolled.
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */1);
$this->assertRegExp('/'.$page22->title.'/', $res->content);
$this->assertRegExp('/'.$page23->title.'/', $res->content);
$this->assertNotRegExp('/'.$page31->title.'/', $res->content);
// User can search wiki pages inside a course.
$coursecontext = context_course::instance($course1->id);
$res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
/*$fromctx = */0, /*$ctx = */$coursecontext->id, /*$rec = */1, /*$page = */0);
$this->assertRegExp('/'.$page11->title.'/', $res->content);
$this->assertRegExp('/'.$page12->title.'/', $res->content);
$this->assertRegExp('/'.$page13->title.'/', $res->content);
$this->assertNotRegExp('/'.$page14->title.'/', $res->content);
$this->assertRegExp('/'.$page15->title.'/', $res->content);
$this->assertNotRegExp('/'.$page21->title.'/', $res->content);
$this->assertNotRegExp('/'.$page22->title.'/', $res->content);
$this->assertNotRegExp('/'.$page23->title.'/', $res->content);
$this->assertEmpty($res->nextpageurl);
}
}
+1 -1
View File
@@ -33,7 +33,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2016011103; // The current module version (Date: YYYYMMDDXX)
$plugin->version = 2016032700; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2015111000; // Requires this Moodle version
$plugin->component = 'mod_wiki'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 0;