public function test_participation() { global $USER; $this->resetAfterTest(true); $this->setAdminUser(); $course = $this->getDataGenerator()->create_course(); $ouwiki = $this->get_new_ouwiki($course->id, OUWIKI_SUBWIKIS_SINGLE); $cm = get_coursemodule_from_instance('ouwiki', $ouwiki->id); $this->assertNotEmpty($cm); $context = context_module::instance($cm->id); $subwiki = ouwiki_get_subwiki($course, $ouwiki, $cm, $context, 0, $USER->id, true); $pageversion = ouwiki_get_current_page($subwiki, 'TEST PAGE', OUWIKI_GETPAGE_CREATE); $user = $this->get_new_user('student', $course->id); $content = 'content'; $plus = ' plus'; for ($i = 1; $i <= 5; $i++) { $content .= $plus . $i; $wordcount = ouwiki_count_words($content); $this->save_new_version($pageversion->pageid, $content, $user->id, $wordcount); } // Remove one word. $content = str_replace('plus3', '', $content); $wordcount = ouwiki_count_words($content); $this->save_new_version($pageversion->pageid, $content, $user->id, $wordcount); // User participation. list($returneduser, $participation) = ouwiki_get_user_participation($user->id, $subwiki); $this->assertEquals($user->id, $returneduser->id); $this->assertNotNull($participation); $this->assertEquals(6, count($participation)); // All participation. $participation = ouwiki_get_participation($ouwiki, $subwiki, $context, 0); $this->assertNotNull($participation); $userexists = array_key_exists($user->id, $participation); $this->assertTrue($userexists); $this->assertEquals(1, count($participation)); $this->assertEquals(6, $participation[$user->id]->pageedits); $this->assertEquals(25, $participation[$user->id]->wordsadded); $this->assertEquals(0, $participation[$user->id]->wordsdeleted); $this->assertEquals(0, $participation[$user->id]->pagecreates); $user2 = $this->get_new_user('student', $course->id); $participation = ouwiki_get_participation($ouwiki, $subwiki, $context, 0); // A user who is enrolled, but with no contribution. $userexists = array_key_exists($user2->id, $participation); $this->assertTrue($userexists); $this->assertEquals(fullname($user2), fullname($participation[$user2->id])); }
/** * Saves a new version of the given named page within a subwiki. Can create * a new page or just add a new version to an existing one. In case of * failure, ends up calling error() rather than returning something. * * @param object $course Course object * @param object $cm Course-module object * @param object $ouwiki OU wiki object * @param object $subwiki Subwiki object * @param string $pagename Name of page (NO SLASHES) * @param string $content XHTML Content (NO SLASHES) * @param int $changestart For section changes. Start position of change. (-1 if not section change) * @param int $changesize Size of changed section. * @param int $changeprevsize Previous size of changed section * @param bool $nouser If true, creates as system * @param object $formdata if coming from edit will have content embedded media and attachments * @param int revertversionid if coming from revert.php will have an older versionid */ function ouwiki_save_new_version($course, $cm, $ouwiki, $subwiki, $pagename, $content, $changestart = -1, $changesize = -1, $changeprevsize = -1, $nouser = null, $formdata = null, $revertversionid = null) { global $DB, $USER; global $ouwikiinternalre, $ouwiki_count; // Nasty but I can't think of a better way! $transaction = $DB->start_delegated_transaction(); // Find page if it exists $pageversion = ouwiki_get_current_page($subwiki, $pagename, OUWIKI_GETPAGE_CREATE); $previousversionid = null; if ($pageversion->currentversionid) { $previousversionid = $pageversion->currentversionid; } // Analyse content for HTML headings that don't already have an ID. // These are all assigned unique, fairly short IDs. // Get number of version [guarantees in-page uniqueness of generated IDs] $versionnumber = $DB->count_records('ouwiki_versions', array('pageid' => $pageversion->pageid)); // Remove any spaces from annotation tags that were added for editing or by users // and remove any duplicate annotation tags $pattern = '~<span\\b.id=\\"annotation(.+?)\\">.*?</span>~'; $replace = '<span id="annotation$1"></span>'; $content = preg_replace($pattern, $replace, $content); unset($pattern, $replace, $used); // Get rid of any heading tags that only contain whitespace $emptypatterns = array(); for ($i = 1; $i <= 6; $i++) { $emptypatterns[] = '~<h' . $i . '[^>]*>\\s*(<br[^>]*>\\s*)*</h' . $i . '>~'; } $content = preg_replace($emptypatterns, '', $content); // List all headings that already have IDs, to check for duplicates $matches = array(); preg_match_all('|<h[1-9] id="ouw_s(.*?)">(.*?)</h[1-9]>|', $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); // Organise list by ID $byid = array(); foreach ($matches as $index => $data) { $id = $data[1][0]; if (!array_key_exists($id, $byid)) { $byid[$id] = array(); } $byid[$id][] = $index; } // Handle any duplicates $deletebits = array(); foreach ($byid as $id => $duplicates) { if (count($duplicates) > 1) { // We have a duplicate. By default, keep the first one $keep = $duplicates[0]; // See if there is a title entry in the database for it $knowntitle = $DB->get_field('ouwiki_sections', 'title', array('xhtmlid' => $id, 'pageid' => $pageversion->pageid)); if ($knowntitle) { foreach ($duplicates as $duplicate) { $title = ouwiki_get_section_title(null, null, $matches[$duplicate][2][0]); if ($title === $knowntitle) { $keep = $duplicate; break; } } } foreach ($duplicates as $duplicate) { if ($duplicate !== $keep) { $deletebits[] = (object) array('startbyte' => $matches[$duplicate][1][1] - 10, 'bytes' => strlen($matches[$duplicate][1][0]) + 11); } } } } // Were there any? if (count($deletebits) > 0) { // Sort in reverse order of starting position usort($deletebits, 'ouwiki_internal_sort_deletions'); // Delete each bit foreach ($deletebits as $deletebit) { $content = substr($content, 0, $deletebit->startbyte) . substr($content, $deletebit->startbyte + $deletebit->bytes); } } // Replace existing empty headings with an ID including version count plus another index $ouwiki_count = 0; $ouwikiinternalre->version = $versionnumber; $ouwikiinternalre->count = 0; $sizebefore = strlen($content); $content = preg_replace_callback('/<h([1-9])>/', 'ouwiki_internal_re_headings', $content); $sizeafter = strlen($content); // Replace wiki links to [[Start page]] with the correct (non // language-specific) format [[]] $regex = str_replace('.*?', preg_quote(get_string('startpage', 'ouwiki')), OUWIKI_LINKS_SQUAREBRACKETS) . 'ui'; $newcontent = @preg_replace($regex, '[[]]', $content); if ($newcontent === null) { // Unicode support not available! Change the regex and try again $regex = preg_replace('~ui$~', 'i', $regex); $newcontent = preg_replace($regex, '[[]]', $content); } $content = $newcontent; // Create version $version = new StdClass(); $version->pageid = $pageversion->pageid; $version->xhtml = $content; // May be altered later (see below) $version->xhtmlformat = FORMAT_MOODLE; // Using fixed value here is a bit rubbish $version->timecreated = time(); $version->wordcount = ouwiki_count_words($content); $version->previousversionid = $previousversionid; if (!$nouser) { $version->userid = $USER->id; } if ($changestart != -1) { $version->changestart = $changestart; // In tracking the new size, account for any added headings etc $version->changesize = $changesize + ($sizeafter - $sizebefore); $version->changeprevsize = $changeprevsize; } try { $versionid = $DB->insert_record('ouwiki_versions', $version); // if firstversionid is already set in the current page use that // else this is a new page and version entirely if (!$pageversion->firstversionid) { $DB->set_field('ouwiki_pages', 'firstversionid', $versionid, array('id' => $version->pageid)); } } catch (Exception $e) { ouwiki_dberror($e); } // information needed for attachments $fs = get_file_storage(); $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); $prevversion = $revertversionid ? $revertversionid : $pageversion->versionid; // save new files connected with the version from the formdata if set if ($formdata) { $formdata->content = file_save_draft_area_files($formdata->content['itemid'], $modcontext->id, 'mod_ouwiki', 'content', $versionid, array('subdirs' => 0), $content); if ($content !== $formdata->content) { $DB->set_field('ouwiki_versions', 'xhtml', $formdata->content, array('id' => $versionid)); } if (isset($formdata->attachments)) { file_save_draft_area_files($formdata->attachments, $modcontext->id, 'mod_ouwiki', 'attachment', $versionid, array('subdirs' => 0)); } } else { // need to copy over attached files from the previous version when // editing without using form if ($oldfiles = $fs->get_area_files($modcontext->id, 'mod_ouwiki', 'attachment', $prevversion)) { foreach ($oldfiles as $oldfile) { // copy this file to the version record. $fs->create_file_from_storedfile(array('contextid' => $modcontext->id, 'filearea' => 'attachment', 'itemid' => $versionid), $oldfile); } } if ($oldfiles = $fs->get_area_files($modcontext->id, 'mod_ouwiki', 'content', $prevversion)) { foreach ($oldfiles as $oldfile) { // copy this file to the version record. $fs->create_file_from_storedfile(array('contextid' => $modcontext->id, 'filearea' => 'content', 'itemid' => $versionid), $oldfile); } } } // Update latest version $DB->set_field('ouwiki_pages', 'currentversionid', $versionid, array('id' => $pageversion->pageid)); // Analyse for links $wikilinks = array(); $externallinks = array(); // Wiki links: ordinary [[links]] $matches = array(); preg_match_all(OUWIKI_LINKS_SQUAREBRACKETS, $content, $matches, PREG_PATTERN_ORDER); foreach ($matches[1] as $match) { // Convert to page name (this also removes HTML tags etc) $wikilinks[] = ouwiki_get_wiki_link_details($match)->page; } // Note that we used to support CamelCase links but have removed support because: // 1. Confusing: students type JavaScript or MySpace and don't expect it to become a link // 2. Not accessible: screenreaders cannot cope with run-together words, and // dyslexic students can have difficulty reading them // External links preg_match_all('/<a [^>]*href=(?:(?:\'(.*?)\')|(?:"(.*?))")/', $content, $matches, PREG_PATTERN_ORDER); foreach ($matches[1] as $match) { if ($match) { $externallinks[] = html_entity_decode($match); } } foreach ($matches[2] as $match) { if ($match) { $externallinks[] = html_entity_decode($match); } } // Add link records $link = new StdClass(); $link->fromversionid = $versionid; foreach ($wikilinks as $targetpage) { if (!empty($targetpage)) { $pagerecord = $DB->get_record_select('ouwiki_pages', 'subwikiid = ? AND UPPER(title) = UPPER(?)', array($subwiki->id, $targetpage)); if ($pagerecord) { $pageid = $pagerecord->id; } else { $pageid = false; } } else { $pageid = $DB->get_field_select('ouwiki_pages', 'id', 'subwikiid = ? AND title IS NULL', array($subwiki->id)); } if ($pageid) { $link->topageid = $pageid; $link->tomissingpage = null; } else { $link->topageid = null; $link->tomissingpage = strtoupper($targetpage); } try { $link->id = $DB->insert_record('ouwiki_links', $link); } catch (Exception $e) { ouwiki_dberror($e); } } $link->topageid = null; $link->tomissingpage = null; $tl = textlib_get_instance(); foreach ($externallinks as $url) { // Restrict length of URL if ($tl->strlen($url) > 255) { $url = $tl->substr($url, 0, 255); } $link->tourl = $url; try { $link->id = $DB->insert_record('ouwiki_links', $link); } catch (Exception $e) { ouwiki_dberror($e); } } // Inform search, if installed if (ouwiki_search_installed()) { $doc = new local_ousearch_document(); $doc->init_module_instance('ouwiki', $cm); if ($subwiki->groupid) { $doc->set_group_id($subwiki->groupid); } $doc->set_string_ref($pageversion->title === '' ? null : $pageversion->title); if ($subwiki->userid) { $doc->set_user_id($subwiki->userid); } $title = $pageversion->title; $doc->update($title, $content); } $transaction->allow_commit(); }
protected function process_ouwiki_version($data) { global $CFG; $data = (object) $data; $oldid = $data->id; $data->pageid = $this->get_new_parentid('ouwiki_page'); if (!isset($data->wordcount)) { // calculate the wordcount if it doesn't exist require_once $CFG->dirroot . '/mod/ouwiki/locallib.php'; $wordcount = ouwiki_count_words($data->xhtml); $data->wordcount = $wordcount; } // Store the version in memory. We cannot write it out now because // they need to be in id order, but the stupid backup can be in random // order (Moodle backup doesn't let you sort it) and there is no way // to fix this before getting here... $this->versions[$oldid] = $data; // Store the current version in memory so we can store links inside // it from the process_ouwiki_link function. $data->links = array(); $this->processingversion = $data; }
function xmldb_ouwiki_upgrade($oldversion = 0) { global $CFG, $DB; $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes. if ($oldversion < 2008100600) { // Define field deletedat to be added to ouwiki_versions. $table = new xmldb_table('ouwiki_versions'); $field = new xmldb_field('deletedat'); $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, 'changeprevsize'); // Launch add field deletedat (provided field does not already exist). if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2008100600, 'ouwiki'); } if ($oldversion < 2009120801) { // Launch create table for ouwiki_annotations - if it does not already exist (extra precaution). $table = new xmldb_table('ouwiki_annotations'); if (!$dbman->table_exists($table)) { $dbman->install_one_table_from_xmldb_file($CFG->dirroot . '/mod/ouwiki/db/install.xml', 'ouwiki_annotations'); } // Define field locked to be added to ouwiki_pages. $table = new xmldb_table('ouwiki_pages'); $field = new xmldb_field('locked'); $field->set_attributes(XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'currentversionid'); // Launch add field locked - if it does not already exist (extra precaution). if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2009120801, 'ouwiki'); } if ($oldversion < 2010022300) { // Define field locked to be added to ouwiki_pages. $table = new xmldb_table('ouwiki'); $field = new xmldb_field('commenting'); $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, null, null, 'default', 'completionedits'); // Launch add field locked - if it does not already exist (extra precaution). if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2010022300, 'ouwiki'); } if ($oldversion < 2010122001) { // Drop the old comments table $table = new xmldb_table('ouwiki_comments'); if ($dbman->table_exists($table)) { $dbman->drop_table($table); } // Drop the old commenting field in ouwiki $table2 = new xmldb_table('ouwiki'); $field = new xmldb_field('commenting'); if ($dbman->field_exists($table2, $field)) { // We need to know about any wikis which are currently // using annotation or both systems before the upgrade // we need these before we drop the commenting field $rs = $DB->get_records_sql("SELECT DISTINCT w.id " . "FROM {ouwiki} w " . "WHERE w.commenting = 'annotations' OR w.commenting = 'both'"); $dbman->drop_field($table2, $field); } // Define field annotation to be added to ouwiki $field2 = new xmldb_field('annotation'); $field2->set_attributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'completionedits'); if (!$dbman->field_exists($table2, $field2)) { $dbman->add_field($table2, $field2); } // update the existing wikis to have annotation turned on // where they did before or had the BOTH commenting option if (!empty($rs)) { $ids = array_keys($rs); list($usql, $params) = $DB->get_in_or_equal($ids); $update_sql = 'UPDATE {ouwiki} SET annotation = 1 WHERE id ' . $usql; $DB->execute($update_sql, $params); } // retrieve new summary field $field3 = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'template'); // Launch rename field summary if ($dbman->field_exists($table2, $field3)) { $dbman->rename_field($table2, $field3, 'intro'); } // Define field introformat to be added to ouwiki $field4 = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'annotation'); // Launch add field introformat if (!$dbman->field_exists($table2, $field4)) { $dbman->add_field($table2, $field4); } // Define field introformat to be added to ouwiki $table3 = new xmldb_table('ouwiki_versions'); $field5 = new xmldb_field('xhtmlformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'deletedat'); // Launch add field introformat if (!$dbman->field_exists($table3, $field5)) { $dbman->add_field($table3, $field5); } // conditionally migrate to html format in intro if ($CFG->texteditors !== 'textarea') { // introformat $rs = $DB->get_recordset('ouwiki', array('introformat' => FORMAT_MOODLE), '', 'id,intro,introformat'); foreach ($rs as $r) { $r->intro = text_to_html($r->intro, false, false, true); $r->introformat = FORMAT_HTML; $DB->update_record('ouwiki', $r); upgrade_set_timeout(); } $rs->close(); // xhtmlformat $rs = $DB->get_recordset('ouwiki_versions', array('xhtmlformat' => FORMAT_MOODLE), '', 'id,xhtml,xhtmlformat'); foreach ($rs as $r) { $r->xhtml = text_to_html($r->xhtml, false, false, true); $r->xhtmlformat = FORMAT_MOODLE; $DB->update_record('ouwiki_versions', $r); upgrade_set_timeout(); } $rs->close(); } upgrade_mod_savepoint(true, 2010122001, 'ouwiki'); } if ($oldversion < 2011031800) { upgrade_mod_savepoint(true, 2011031800, 'ouwiki'); } if ($oldversion < 2011060100) { // Define field enablewordcount to be added to ouwiki $table = new xmldb_table('ouwiki'); $field = new xmldb_field('enablewordcount', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1', 'introformat'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Define field wordcount to be added to ouwiki_versions $table = new xmldb_table('ouwiki_versions'); $field = new xmldb_field('wordcount', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'xhtmlformat'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // we need to update all ouwiki_versions wordcounts $count = $DB->count_records_sql('SELECT COUNT(*) FROM {ouwiki_versions}'); $rs = $DB->get_recordset_sql('SELECT id, xhtml FROM {ouwiki_versions} ORDER BY id'); if ($rs->valid()) { $pbar = new progress_bar('countwordsouwikiversionsxhtml', 500, true); $i = 0; foreach ($rs as $entry) { $i++; upgrade_set_timeout(60); // set up timeout, may also abort execution $pbar->update($i, $count, "Counting words of ouwiki version entries - {$i}/{$count}."); // retrieve wordcount require_once $CFG->dirroot . '/mod/ouwiki/locallib.php'; $wordcount = ouwiki_count_words($entry->xhtml); $entry->wordcount = $wordcount; $DB->update_record('ouwiki_versions', $entry); } } $rs->close(); upgrade_mod_savepoint(true, 2011060100, 'ouwiki'); } if ($oldversion < 2011071300) { // Define field grade to be added to ouwiki $table = new xmldb_table('ouwiki'); $field = new xmldb_field('grade', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'enablewordcount'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // we need to update all ouwiki_versions scales $rs = $DB->get_recordset_sql('SELECT id FROM {ouwiki} ORDER BY id'); if ($rs->valid()) { foreach ($rs as $entry) { $entry->grade = 0; $DB->update_record('ouwiki', $entry); } } $rs->close(); upgrade_mod_savepoint(true, 2011071300, 'ouwiki'); } if ($oldversion < 2011072000) { // Define field firstversionid to be added to ouwiki_pages $table = new xmldb_table('ouwiki_pages'); $field = new xmldb_field('firstversionid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, '0', 'locked'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Define field previousversionid to be added to ouwiki_versions $table = new xmldb_table('ouwiki_versions'); $field = new xmldb_field('previousversionid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, '0', 'wordcount'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // update all ouwiki_versions previousversionids and ouwiki_pages firstversionids // firstversionid $sql = 'SELECT v.pageid, (SELECT MIN(id) FROM {ouwiki_versions} v3 WHERE v3.pageid = p.id AND v3.deletedat IS NULL) AS firstversionid FROM {ouwiki_pages} p JOIN {ouwiki_versions} v ON v.pageid = p.id GROUP BY v.pageid, p.id ORDER BY v.pageid'; $rs = $DB->get_recordset_sql($sql); if ($rs->valid()) { foreach ($rs as $entry) { if (isset($entry->firstversionid)) { $DB->set_field('ouwiki_pages', 'firstversionid', $entry->firstversionid, array('id' => $entry->pageid)); } } } $rs->close(); // previousversionid $count = $DB->count_records_sql('SELECT COUNT(*) FROM {ouwiki_versions}'); $sql = 'SELECT v.id AS versionid, (SELECT MAX(v2.id) FROM {ouwiki_versions} v2 WHERE v2.pageid = p.id AND v2.id < v.id) AS previousversionid FROM {ouwiki_pages} p JOIN {ouwiki_versions} v ON v.pageid = p.id'; $rs = $DB->get_recordset_sql($sql); if ($rs->valid()) { $pbar = new progress_bar('ouwikifirstandpreviousversions', 500, true); $i = 0; foreach ($rs as $entry) { $i++; upgrade_set_timeout(60); // set up timeout, may also abort execution $pbar->update($i, $count, "Updating wiki metadata - {$i}/{$count}."); if (isset($entry->previousversionid)) { $DB->set_field('ouwiki_versions', 'previousversionid', $entry->previousversionid, array('id' => $entry->versionid)); } } } $rs->close(); upgrade_mod_savepoint(true, 2011072000, 'ouwiki'); } if ($oldversion < 2011102802) { // Delete any duplicate null values (these aren't caught by index) // Done in two stages in case mysql is a piece of ****. $rs = $DB->get_recordset_sql("\nSELECT\n p.id\nFROM\n {ouwiki_pages} p\n LEFT JOIN {ouwiki_pages} p2 ON p2.subwikiid = p.subwikiid AND p2.title IS NULL\n AND p.title IS NULL AND p2.id < p.id\nWHERE\n p2.id IS NOT NULL"); $ids = array(); foreach ($rs as $rec) { $ids[] = $rec->id; } $rs->close(); if ($ids) { list($sql, $params) = $DB->get_in_or_equal($ids); $DB->execute("DELETE FROM {ouwiki_pages} WHERE id {$sql}", $params); } // Set all the null values to blank $DB->execute("UPDATE {ouwiki_pages} SET title='' WHERE title IS NULL"); // Also in ousearch table if installed $table = new xmldb_table('local_ousearch_documents'); if ($dbman->table_exists($table)) { $DB->execute("UPDATE {local_ousearch_documents} SET stringref='' WHERE stringref IS NULL AND plugin='mod_ouwiki'"); } // Changing nullability of field title on table ouwiki_pages to not null $table = new xmldb_table('ouwiki_pages'); $field = new xmldb_field('title', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'subwikiid'); // Launch change of nullability for field title $dbman->change_field_notnull($table, $field); // Define index subwikiid-title (unique) to be added to ouwiki_pages $index = new xmldb_index('subwikiid-title', XMLDB_INDEX_UNIQUE, array('subwikiid', 'title')); // Conditionally launch add index subwikiid-title if (!$dbman->index_exists($table, $index)) { $dbman->add_index($table, $index); } // ouwiki savepoint reached upgrade_mod_savepoint(true, 2011102802, 'ouwiki'); } if ($oldversion < 2013060600) { // Fix broken links due to annotations (current version unlocked page only). $likes = $DB->sql_like('l.tourl', '?'); $params = array('view.php%'); // Fix where relative has been turned into incorrect absolute. $likes .= ' or ' . $DB->sql_like('l.tourl', '?'); $params[] = "{$CFG->wwwroot}/view.php%"; // Only pickup links on pages where annotations have been used. $pagelike = $DB->sql_like('v.xhtml', '?'); $params[] = '<div class="ouwiki_content"%'; $params[] = 0; $sql = "select l.id as lid, l.tourl, v.id as vid, v.xhtml, p.id as pageid, p.subwikiid\n from {ouwiki_links} l\n inner join {ouwiki_versions} v on v.id = l.fromversionid\n inner join {ouwiki_pages} p on v.id = p.currentversionid\n where ({$likes})\n and {$pagelike} and p.locked = ?\n order by p.id"; $links = $DB->get_records_sql($sql, $params); $pagesprocessed = array(); $subwikipages = array(); foreach ($links as $linkdetails) { // For each link found fix content of page it belongs to (once per page). if (!in_array($linkdetails->pageid, $pagesprocessed)) { // Tidy up and revert converted content (links) back to original format. $pattern = '(<a\\b[^>]*?href="(' . preg_quote($CFG->wwwroot . '/') . ')?view\\.php[^"]*?page=([^"]*?)"[^>]*?>(.*?)<\\/a>)'; preg_match_all($pattern, $linkdetails->xhtml, $matches); $newxhtml = $linkdetails->xhtml; for ($i = 0; $i < count($matches[0]); $i++) { $tag = $matches[0][$i]; $page = urldecode($matches[2][$i]); $text = $matches[3][$i]; if (strip_tags($text) == $text) { // Only create 'proper' link where tag contents not formatted. $newxhtml = str_replace($tag, "[[{$page}]]", $newxhtml); } else { if (!empty($matches[1][$i])) { // Fix link if absolute to incorrect path. $newtag = str_replace("{$CFG->wwwroot}/view.php", "{$CFG->wwwroot}/mod/ouwiki/view.php", $tag); $newxhtml = str_replace($tag, $newtag, $newxhtml); } else { // Fix relative links to view.php as these break when page is edited. $newtag = str_replace('"view.php', "\"{$CFG->wwwroot}/mod/ouwiki/view.php", $tag); $newxhtml = str_replace($tag, $newtag, $newxhtml); } } } if ($newxhtml != $linkdetails->xhtml) { // Save updated page content. $update = new stdClass(); $update->id = $linkdetails->vid; $update->xhtml = $newxhtml; $DB->update_record('ouwiki_versions', $update); } $pagesprocessed[] = $linkdetails->pageid; // Don't process again. } // Attempt to turn tourl link into 'proper' wiki link so structure is correct. if (!isset($subwikipages[$linkdetails->subwikiid])) { // Store all pages from the subwiki (once) so we can find the relevant page. $subwikipages[$linkdetails->subwikiid] = $DB->get_records('ouwiki_pages', array('subwikiid' => $linkdetails->subwikiid), '', 'id,title'); } $pagetitle = ''; if ($pagechar = strpos($linkdetails->tourl, 'page=')) { // Get page title from url (always at end of url). $pagetitle = urldecode(substr($linkdetails->tourl, $pagechar + 5)); } $pageid = 0; // Find page title in sub wiki pages (includes start page match). if (!empty($subwikipages[$linkdetails->subwikiid])) { foreach ($subwikipages[$linkdetails->subwikiid] as $page) { if ($page->title === $pagetitle) { $pageid = $page->id; break; } } } // Update link record (will always tidy regardless). $update = new stdClass(); $update->id = $linkdetails->lid; $update->tourl = null; if ($pageid) { $update->topageid = $pageid; } else { $update->tomissingpage = strtoupper($pagetitle); } $DB->update_record('ouwiki_links', $update); } $links = null; $subwikipages = null; // ouwiki savepoint reached. upgrade_mod_savepoint(true, 2013060600, 'ouwiki'); } if ($oldversion < 2014012700) { // Define field allowimport to be added to ouwiki. $table = new xmldb_table('ouwiki'); $field = new xmldb_field('allowimport', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'grade'); // Conditionally launch add field allowimport. if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Define field importversionid to be added to ouwiki_versions. $table = new xmldb_table('ouwiki_versions'); $field = new xmldb_field('importversionid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'previousversionid'); // Conditionally launch add field importversionid. if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Ouwiki savepoint reached. upgrade_mod_savepoint(true, 2014012700, 'ouwiki'); } if ($oldversion < 2014031100) { // Define index ouwiki_subwikis_unique_group (unique) to be added to ouwiki_subwikis. $table = new xmldb_table('ouwiki_subwikis'); $index = new xmldb_index('ouwiki_subwikis_unique_group', XMLDB_INDEX_UNIQUE, array('wikiid', 'groupid')); // Conditionally launch add index ouwiki_subwikis_unique_group. if (!$dbman->index_exists($table, $index)) { $dbman->add_index($table, $index); } // Define index ouwiki_subwikis_unique_user (unique) to be added to ouwiki_subwikis. $table = new xmldb_table('ouwiki_subwikis'); $index = new xmldb_index('ouwiki_subwikis_unique_user', XMLDB_INDEX_UNIQUE, array('wikiid', 'userid')); // Conditionally launch add index ouwiki_subwikis_unique_user. if (!$dbman->index_exists($table, $index)) { $dbman->add_index($table, $index); } // Ouwiki savepoint reached. upgrade_mod_savepoint(true, 2014031100, 'ouwiki'); } // Must always return true from these functions return true; }
function xmldb_ouwiki_upgrade($oldversion = 0) { global $CFG, $DB; $dbman = $DB->get_manager(); /// loads ddl manager and xmldb classes if ($oldversion < 2008100600) { /// Define field deletedat to be added to ouwiki_versions $table = new xmldb_table('ouwiki_versions'); $field = new xmldb_field('deletedat'); $field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, 'changeprevsize'); /// Launch add field deletedat (provided field does not already exist) if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2008100600, 'ouwiki'); } if ($oldversion < 2009120801) { /// Launch create table for ouwiki_annotations - if it does not already exist (extra precaution) $table = new xmldb_table('ouwiki_annotations'); if (!$dbman->table_exists($table)) { $dbman->install_one_table_from_xmldb_file($CFG->dirroot . '/mod/ouwiki/db/install.xml', 'ouwiki_annotations'); } /// Define field locked to be added to ouwiki_pages $table = new xmldb_table('ouwiki_pages'); $field = new xmldb_field('locked'); $field->set_attributes(XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'currentversionid'); /// Launch add field locked - if it does not already exist (extra precaution) if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2009120801, 'ouwiki'); } if ($oldversion < 2010022300) { /// Define field locked to be added to ouwiki_pages $table = new xmldb_table('ouwiki'); $field = new xmldb_field('commenting'); $field->set_attributes(XMLDB_TYPE_CHAR, '20', null, null, null, 'default', 'completionedits'); /// Launch add field locked - if it does not already exist (extra precaution) if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } upgrade_mod_savepoint(true, 2010022300, 'ouwiki'); } if ($oldversion < 2010122001) { // Drop the old comments table $table = new xmldb_table('ouwiki_comments'); if ($dbman->table_exists($table)) { $dbman->drop_table($table); } // Drop the old commenting field in ouwiki $table2 = new xmldb_table('ouwiki'); $field = new xmldb_field('commenting'); if ($dbman->field_exists($table2, $field)) { // We need to know about any wikis which are currently // using annotation or both systems before the upgrade // we need these before we drop the commenting field $rs = $DB->get_records_sql("SELECT DISTINCT w.id " . "FROM {ouwiki} w " . "WHERE w.commenting = 'annotations' OR w.commenting = 'both'"); $dbman->drop_field($table2, $field); } // Define field annotation to be added to ouwiki $field2 = new xmldb_field('annotation'); $field2->set_attributes(XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'completionedits'); if (!$dbman->field_exists($table2, $field2)) { $dbman->add_field($table2, $field2); } // update the existing wikis to have annotation turned on // where they did before or had the BOTH commenting option if (!empty($rs)) { $ids = array_keys($rs); list($usql, $params) = $DB->get_in_or_equal($ids); $update_sql = 'UPDATE {ouwiki} SET annotation = 1 WHERE id ' . $usql; $DB->execute($update_sql, $params); } // retrieve new summary field $field3 = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'template'); // Launch rename field summary if ($dbman->field_exists($table2, $field3)) { $dbman->rename_field($table2, $field3, 'intro'); } // Define field introformat to be added to ouwiki $field4 = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'annotation'); // Launch add field introformat if (!$dbman->field_exists($table2, $field4)) { $dbman->add_field($table2, $field4); } // Define field introformat to be added to ouwiki $table3 = new xmldb_table('ouwiki_versions'); $field5 = new xmldb_field('xhtmlformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'deletedat'); // Launch add field introformat if (!$dbman->field_exists($table3, $field5)) { $dbman->add_field($table3, $field5); } // conditionally migrate to html format in intro if ($CFG->texteditors !== 'textarea') { // introformat $rs = $DB->get_recordset('ouwiki', array('introformat' => FORMAT_MOODLE), '', 'id,intro,introformat'); foreach ($rs as $r) { $r->intro = text_to_html($r->intro, false, false, true); $r->introformat = FORMAT_HTML; $DB->update_record('ouwiki', $r); upgrade_set_timeout(); } $rs->close(); // xhtmlformat $rs = $DB->get_recordset('ouwiki_versions', array('xhtmlformat' => FORMAT_MOODLE), '', 'id,xhtml,xhtmlformat'); foreach ($rs as $r) { $r->xhtml = text_to_html($r->xhtml, false, false, true); $r->xhtmlformat = FORMAT_MOODLE; $DB->update_record('ouwiki_versions', $r); upgrade_set_timeout(); } $rs->close(); } upgrade_mod_savepoint(true, 2010122001, 'ouwiki'); } if ($oldversion < 2011031800) { upgrade_mod_savepoint(true, 2011031800, 'ouwiki'); } if ($oldversion < 2011060100) { // Define field enablewordcount to be added to ouwiki $table = new xmldb_table('ouwiki'); $field = new xmldb_field('enablewordcount', XMLDB_TYPE_INTEGER, '1', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '1', 'introformat'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Define field wordcount to be added to ouwiki_versions $table = new xmldb_table('ouwiki_versions'); $field = new xmldb_field('wordcount', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'xhtmlformat'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // we need to update all ouwiki_versions wordcounts $count = $DB->count_records_sql('SELECT COUNT(*) FROM {ouwiki_versions}'); $rs = $DB->get_recordset_sql('SELECT id, xhtml FROM {ouwiki_versions} ORDER BY id'); if ($rs->valid()) { $pbar = new progress_bar('countwordsouwikiversionsxhtml', 500, true); $i = 0; foreach ($rs as $entry) { $i++; upgrade_set_timeout(60); // set up timeout, may also abort execution $pbar->update($i, $count, "Counting words of ouwiki version entries - {$i}/{$count}."); // retrieve wordcount require_once $CFG->dirroot . '/mod/ouwiki/locallib.php'; $wordcount = ouwiki_count_words($entry->xhtml); $entry->wordcount = $wordcount; $DB->update_record('ouwiki_versions', $entry); } } $rs->close(); upgrade_mod_savepoint(true, 2011060100, 'ouwiki'); } if ($oldversion < 2011071300) { // Define field grade to be added to ouwiki $table = new xmldb_table('ouwiki'); $field = new xmldb_field('grade', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'enablewordcount'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // we need to update all ouwiki_versions scales $rs = $DB->get_recordset_sql('SELECT id FROM {ouwiki} ORDER BY id'); if ($rs->valid()) { foreach ($rs as $entry) { $entry->grade = 0; $DB->update_record('ouwiki', $entry); } } $rs->close(); upgrade_mod_savepoint(true, 2011071300, 'ouwiki'); } if ($oldversion < 2011072000) { // Define field firstversionid to be added to ouwiki_pages $table = new xmldb_table('ouwiki_pages'); $field = new xmldb_field('firstversionid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, '0', 'locked'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // Define field previousversionid to be added to ouwiki_versions $table = new xmldb_table('ouwiki_versions'); $field = new xmldb_field('previousversionid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, '0', 'wordcount'); if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } // update all ouwiki_versions previousversionids and ouwiki_pages firstversionids // firstversionid $sql = 'SELECT v.pageid, (SELECT MIN(id) FROM {ouwiki_versions} v3 WHERE v3.pageid = p.id AND v3.deletedat IS NULL) AS firstversionid FROM {ouwiki_pages} p JOIN {ouwiki_versions} v ON v.pageid = p.id GROUP BY v.pageid, p.id ORDER BY v.pageid'; $rs = $DB->get_recordset_sql($sql); if ($rs->valid()) { foreach ($rs as $entry) { if (isset($entry->firstversionid)) { $DB->set_field('ouwiki_pages', 'firstversionid', $entry->firstversionid, array('id' => $entry->pageid)); } } } $rs->close(); // previousversionid $count = $DB->count_records_sql('SELECT COUNT(*) FROM {ouwiki_versions}'); $sql = 'SELECT v.id AS versionid, (SELECT MAX(v2.id) FROM {ouwiki_versions} v2 WHERE v2.pageid = p.id AND v2.id < v.id) AS previousversionid FROM {ouwiki_pages} p JOIN {ouwiki_versions} v ON v.pageid = p.id'; $rs = $DB->get_recordset_sql($sql); if ($rs->valid()) { $pbar = new progress_bar('ouwikifirstandpreviousversions', 500, true); $i = 0; foreach ($rs as $entry) { $i++; upgrade_set_timeout(60); // set up timeout, may also abort execution $pbar->update($i, $count, "Updating wiki metadata - {$i}/{$count}."); if (isset($entry->previousversionid)) { $DB->set_field('ouwiki_versions', 'previousversionid', $entry->previousversionid, array('id' => $entry->versionid)); } } } $rs->close(); upgrade_mod_savepoint(true, 2011072000, 'ouwiki'); } if ($oldversion < 2011102802) { // Delete any duplicate null values (these aren't caught by index) // Done in two stages in case mysql is a piece of ****. $rs = $DB->get_recordset_sql("\nSELECT\n p.id\nFROM\n {ouwiki_pages} p\n LEFT JOIN {ouwiki_pages} p2 ON p2.subwikiid = p.subwikiid AND p2.title IS NULL\n AND p.title IS NULL AND p2.id < p.id\nWHERE\n p2.id IS NOT NULL"); $ids = array(); foreach ($rs as $rec) { $ids[] = $rec->id; } $rs->close(); if ($ids) { list($sql, $params) = $DB->get_in_or_equal($ids); $DB->execute("DELETE FROM {ouwiki_pages} WHERE id {$sql}", $params); } // Set all the null values to blank $DB->execute("UPDATE {ouwiki_pages} SET title='' WHERE title IS NULL"); // Also in ousearch table if installed $table = new xmldb_table('local_ousearch_documents'); if ($dbman->table_exists($table)) { $DB->execute("UPDATE {local_ousearch_documents} SET stringref='' WHERE stringref IS NULL AND plugin='mod_ouwiki'"); } // Changing nullability of field title on table ouwiki_pages to not null $table = new xmldb_table('ouwiki_pages'); $field = new xmldb_field('title', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'subwikiid'); // Launch change of nullability for field title $dbman->change_field_notnull($table, $field); // Define index subwikiid-title (unique) to be added to ouwiki_pages $index = new xmldb_index('subwikiid-title', XMLDB_INDEX_UNIQUE, array('subwikiid', 'title')); // Conditionally launch add index subwikiid-title if (!$dbman->index_exists($table, $index)) { $dbman->add_index($table, $index); } // ouwiki savepoint reached upgrade_mod_savepoint(true, 2011102802, 'ouwiki'); } // Must always return true from these functions return true; }
function test_ouwiki_word_count() { $tests = array(); $test['string'] = "This is four words"; $test['count'] = 4; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = " "; $test['count'] = 0; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = "word"; $test['count'] = 1; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = "Two\n\nwords"; $test['count'] = 2; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = "<p><b>two <i>words</i></b></p>"; $test['count'] = 2; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = "Isn’t it three"; $test['count'] = 3; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = "Isn't it three"; $test['count'] = 3; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = "three-times-hyphenated words"; $test['count'] = 2; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = "one,two,さん"; $test['count'] = 3; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); $test['string'] = 'Two words '; $test['count'] = 2; $testcount = ouwiki_count_words($test['string']); $this->assertEqual($testcount, $test['count']); }
public function test_participation() { $ouwiki = $this->get_new_ouwiki($this->courses['single']->id, OUWIKI_SUBWIKIS_SINGLE); $cm = $this->get_new_course_module($this->courses['single']->id, $ouwiki->id, NOGROUPS); $context = get_context_instance(CONTEXT_MODULE, $cm->id); $subwiki = ouwiki_get_subwiki($this->courses['single'], $ouwiki, $cm, $context, 0, $this->admin->id, true); $pageversion = ouwiki_get_current_page($subwiki, 'TEST PAGE', OUWIKI_GETPAGE_CREATE); $user = $this->get_new_user('student'); $content = 'content'; $plus = ' plus'; for ($i = 1; $i <= 5; $i++) { $content .= $plus . $i; $wordcount = ouwiki_count_words($content); $this->save_new_version($pageversion->pageid, $content, $user->id, $wordcount); } // remove one word $content = preg_replace('/plus3/', '', $content); $wordcount = ouwiki_count_words($content); $this->save_new_version($pageversion->pageid, $content, $user->id, $wordcount); list($returneduser, $participation) = ouwiki_get_user_participation($user->id, $subwiki); $this->assertEqual($returneduser->id, $user->id); $this->assertNotNull($participation); // another user $user2 = $this->get_new_user('student'); $users[0] = $user->id; $users[1] = $user2->id; $participation = ouwiki_get_participation($ouwiki, $subwiki, $context, 0); $this->assertNotNull($participation); $userexists = array_key_exists($user->id, $participation); $this->assertTrue($userexists); // a user who isn't enrolled $userexists = array_key_exists($this->nouser->id, $participation); $this->assertFalse($userexists); }
protected function process_ouwiki_version($data) { global $DB, $CFG; $data = (object) $data; $oldid = $data->id; $data->pageid = $this->get_new_parentid('ouwiki_page'); if (!isset($data->wordcount)) { // calculate the wordcount if it doesn't exist require_once $CFG->dirroot . '/mod/ouwiki/locallib.php'; $wordcount = ouwiki_count_words($data->xhtml); $data->wordcount = $wordcount; } $newitemid = $DB->insert_record('ouwiki_versions', $data); $this->set_mapping('ouwiki_version', $oldid, $newitemid, true); // see if this version was the "currentversion" in the old database $page = $DB->get_record('ouwiki_pages', array('id' => $data->pageid), 'id, currentversionid'); if ($oldid == $page->currentversionid) { $page->currentversionid = $newitemid; $DB->update_record('ouwiki_pages', $page); } }