diff --git a/mod/wiki/db/migration/lib.php b/mod/wiki/db/migration/lib.php index 63aaa4cd7e6..b65a3d5304d 100644 --- a/mod/wiki/db/migration/lib.php +++ b/mod/wiki/db/migration/lib.php @@ -1,4 +1,12 @@ disablecamelcase == 1); - // Block of dinamic ewiki defines + // Block of dinamic ewiki defines wiki_set_define("EWIKI_NAME", $wiki_entry->pagename); wiki_set_define("EWIKI_DEFAULT_LANG", current_language()); if ($moodle_disable_camel_case) { @@ -48,8 +56,7 @@ function wiki_ewiki_2_html($oldentry, $oldpage, $oldwiki) { $content = ewiki_format($oldpage->content); - return format_text($content, $moodle_format); - + return $content; } function wiki_set_define($key, $value) { @@ -64,3 +71,512 @@ function wiki_get_define($key) { return $ewikidefines[$key]; } +function ewiki_mime_magic($binary_data) { + $mime_magic_data = array( + array(0, 2, 0, "\x06\x02", "application/x-alan-adventure-game"), + array(0, 4, 0, "TADS", "application/x-tads-game"), + array(0, 2, 0, "\x01\x10", "application/x-executable-file"), + array(0, 2, 0, "\x01\x11", "application/x-executable-file"), + array(0, 2, 0, "\x01ƒ", "application/x-executable-file"), + array(0, 5, 0, "Core\001", "application/x-executable-file"), + array(0, 22, 0, "AMANDA: TAPESTART DATE", "application/x-amanda-header"), + array(0, 2, 0xfff0, 0xf0ff, "audio/mpeg"), + array(4, 2, 0, "¯\x11", "video/fli"), + array(4, 2, 0, "¯\x12", "video/flc"), + array(0, 4, 0, "MOVI", "video/x-sgi-movie"), + array(4, 4, 0, "moov", "video/quicktime"), + array(4, 4, 0, "mdat", "video/quicktime"), + array(0, 18, 0, "FiLeStArTfIlEsTaRt", "text/x-apple-binscii"), + array(0, 3, 0, "\x0aGL", "application/data"), + array(0, 2, 0, "\x76\xff", "application/data"), + array(0, 6, 0, "NuFile", "application/data"), + array(0, 6, 0, "N\xf5F\xe9l\xe5", "application/data"), + array(0, 4, 0, "\x00\x16\x05\x00", "application/data"), + array(0, 4, 0, "\x07\x16\x05\x00", "application/data"), + array(257, 6, 0, "ustar\0", "application/x-tar"), + array(257, 8, 0, "ustar\040\040\0", "application/x-gtar"), + array(0, 2, 0, "qÇ", "application/x-cpio"), + array(0, 2, 0, "Çq", "application/x-bcpio"), + array(0, 6, 0, "070707", "application/x-cpio"), + array(0, 6, 0, "070701", "application/x-cpio"), + array(0, 6, 0, "070702", "application/x-cpio"), + array(0, 2, 0, "ÿm", "application/data"), + array(0, 2, 0, "ÿe", "application/data"), + array(0, 5, 0, "=", "application/x-ar"), + array(0, 19, 0, "!\n__________E", "application/x-ar"), + array(0, 3, 0, "-h-", "application/data"), + array(0, 7, 0, "!", "application/x-ar"), + array(0, 4, 0, "", "application/x-ar"), + array(0, 4, 0, ">ra<", "application/x-ar"), + array(0, 4, 0, "!\n\n________64E", "application/data"), + array(0, 2, 0, "\x01ˆ", "application/x-executable-file"), + array(0, 2, 0, "\x01", "application/x-object-file"), + array(0, 3, 0, "\377\377\177", "application/data"), + array(0, 3, 0, "\377\377\174", "application/data"), + array(0, 3, 0, "\377\377\176", "application/data"), + array(0, 3, 0, "\033c\033", "application/data"), + array(0, 4, 0, "\x00\x12և", "image/x11"), + array(0, 8, 0, "!!\n", "application/x-prof"), + array(0, 2, 0, "\x05\x01", "application/x-locale"), + array(0, 4, 0, "\177ELF", "application/x-executable-file"), + array(0, 2, 0, "\x01T", "application/data"), + array(0, 2, 0, "\x01U", "application/x-executable-file"), + array(0x438, 2, 0, "ïS", "application/x-linux-ext2fs"), + array(0, 4, 0, "\366\366\366\366", "application/x-pc-floppy"), + array(0774, 2, 0, "¾Ú", "application/data"), + array(0x1FE, 2, 0, "ªU", "application/data"), + array(0x410, 2, 0, "\x13", "application/x-filesystem"), + array(0x410, 2, 0, "\x13", "application/x-filesystem"), + array(0x410, 2, 0, "\x24h", "application/x-filesystem"), + array(0x410, 2, 0, "\x24x", "application/x-filesystem"), + array(0, 9, 0, "-rom1fs-\0", "application/x-filesystem"), + array(0, 4, 0, "\x1b\x03\x136", "application/x-bootable"), + array(0x18b, 4, 0, "OS/2", "application/x-bootable"), + array(0, 4, 0, "FONT", "font/x-vfont"), + array(0, 2, 0, "\x01\x1e", "font/x-vfont"), + array(0, 2, 0, "\x1e\x01", "font/x-vfont"), + array(0, 18, 0, "%!PS-AdobeFont-1.0", "font/type1"), + array(6, 18, 0, "%!PS-AdobeFont-1.0", "font/type1"), + array(0, 10, 0, "STARTFONT\040", "font/x-bdf"), + array(0, 4, 0, "\001fcp", "font/x-pcf"), + array(0, 5, 0, "D1.0\015", "font/x-speedo"), + array(0, 3, 0, "flf", "font/x-figlet"), + array(0, 3, 0, "flc", "application/x-font"), + array(0, 4, 0, "\x19Y\x02\x14", "font/x-libgrx"), + array(0, 4, 0, "NOFÿ", "font/x-dos"), + array(7, 4, 0, "AGE\x00", "font/x-dos"), + array(7, 4, 0, "DIV\x00", "font/x-dos"), + array(0, 10, 0, "2', 2, 0, "º¾", "application/java"), + array(8, 4, 0, "AIFF", "audio/x-aiff"), + array(8, 4, 0, "AIFC", "audio/x-aiff"), + array(8, 4, 0, "8SVX", "audio/x-aiff"), + array('>8', 4, 0, "WAVE", "audio/x-wav"), + array('>8', 3, 0, "AVI", "video/x-msvideo"), + array(0, 3, 0, "ID3", "audio/mpeg"), + array(0, 4, 0, "OggS", "audio/x-ogg"), + array(0, 6, 0, "/* XPM", "image/x-xpm"), + array(16, 2, 0, "==", "image/x-3ds"), + array(0, 11, 0, "#!/bin/tcsh", "application/x-shellscript"), + array(0, 12, 0, "#! /bin/tcsh", "application/x-shellscript"), + array(0, 18, 0, "#! /usr/local/tcsh", "application/x-shellscript"), + array('>8', 6, 0, "debian", "application/x-debian-package"), + array('>2', 2, 0, "Ûî", "application/x-rpm"), + array(2, 5, 0, "-lh -", "application/x-lha"), + array(2, 5, 0, "-lh6-", "application/x-lha"), + array(2, 5, 0, "-lh7-", "application/x-lha"), + array(0, 15, 0, "8', 4, 0, "AVI ", "video/avi"), + array(0, 1, 0, "\x01", "video/unknown"), + array(0, 1, 0, "\x02", "video/unknown"), + array(0, 19, 0, "[KDE Desktop Entry]", "application/x-kdelnk"), + array(0, 18, 0, "\# KDE Config File", "application/x-kdelnk"), + array(0, 7, 0, "\# xmcd", "text/xmcd"), + array(0, 4, 0, "\x8aMNG", "video/x-mng"), + array(0, 4, 0, "ó\x03\x00\x00", "application/x-executable-file"), + array(0, 4, 0, "ç\x03\x00\x00", "application/x-library-file"), + array(0, 4, 0, "³\x01\x00\x00", "video/mpeg"), + array(0, 4, 0, "º\x01\x00\x00", "video/mpeg"), + array(0, 4, 0, "\x00\x00l", "application/x-apl-workspace"), + array(0, 4, 0, "\x00\x00ÿm", "application/x-ar"), + array(0, 4, 0, "\x00\x00ÿe", "application/data"), + array(0, 4, 0, "\x00\x00\x01\x06", "application/x-executable-file"), + array(0, 4, 0, "G\x01\x00\x00", "application/x-object-file"), + array(0, 4, 0, "K\x01\x00\x00", "application/x-executable-file"), + array(0, 4, 0, "M\x01\x00\x00", "application/x-executable-file"), + array(0, 4, 0, "O\x01\x00\x00", "application/x-executable-file"), + array(24, 4, 0, "kê\x00\x00", "application/data"), + array(24, 4, 0, "lê\x00\x00", "application/data"), + array(24, 4, 0, "mê\x00\x00", "application/data"), + array(24, 4, 0, "nê\x00\x00", "application/data"), + array(0, 4, 0, "\x01\x00\x00", "application/x-object-file"), + array(0, 4, 0, "‡\x01\x00\x00", "application/data"), + array(24, 4, 0, "\x00\x00êl", "application/x-dump"), + array(24, 4, 0, "\x00\x00êk", "application/x-dump"), + array(0, 4, 0, "\x00\x00¾1", "text/vnd.ms-word"), + array(0, 2, 0, "\x00\x00", "audio/mpeg"), + array('>16', 2, 0, "\x00\x01", "application/x-object"), + array('>16', 2, 0, "\x00\x02", "application/x-executable"), + array('>16', 2, 0, "\x00\x03", "application/x-sharedlib"), + array('>16', 2, 0, "\x00\x04", "application/x-coredump"), + array(0, 4, 0, "\x00\x00\x00Ì", "application/x-executable-file"), + array(0, 4, 0, "\x04\x00\x00\x00", "font/x-snf"), + array(0, 4, 0, "\x00\x00\x00\x04", "font/x-snf"), + array('>12', 4, 0, "\x01\x00\x00\x00", "audio/basic"), + array('>12', 4, 0, "\x02\x00\x00\x00", "audio/basic"), + array('>12', 4, 0, "\x03\x00\x00\x00", "audio/basic"), + array('>12', 4, 0, "\x04\x00\x00\x00", "audio/basic"), + array('>12', 4, 0, "\x05\x00\x00\x00", "audio/basic"), + array('>12', 4, 0, "\x06\x00\x00\x00", "audio/basic"), + array('>12', 4, 0, "\x07\x00\x00\x00", "audio/basic"), + array('>12', 4, 0, "\x17\x00\x00\x00", "audio/x-adpcm"), + array('>12', 4, 0, "\x00\x00\x00\x01", "audio/x-dec-basic"), + array('>12', 4, 0, "\x00\x00\x00\x02", "audio/x-dec-basic"), + array('>12', 4, 0, "\x00\x00\x00\x03", "audio/x-dec-basic"), + array('>12', 4, 0, "\x00\x00\x00\x04", "audio/x-dec-basic"), + array('>12', 4, 0, "\x00\x00\x00\x05", "audio/x-dec-basic"), + array('>12', 4, 0, "\x00\x00\x00\x06", "audio/x-dec-basic"), + array('>12', 4, 0, "\x00\x00\x00\x07", "audio/x-dec-basic"), + array('>12', 4, 0, "\x00\x00\x00\x17", "audio/x-dec-adpcm") + ); + + $fd = substr($binary_data, 0, 3072); + foreach ($mime_magic_data as $def) { + $pos0 = $def[0]; + if ($pos0[0] == ">") { + $pos0 = substr($pos0, 1); + if (@strpos($fd, $def[3], $pos0) !== false) { + return($def[4]); + } + } else { + $part = substr($fd, $pos0, $def[1]); + $mask = $def[2]; + if ($mask) { + // if $mask is 0 + $value = 1 * ('0x'.bin2hex($part)); + if (($value & $mask) == $def[3]) { + return($def[4]); + } + } else { + if ($part == $def[3]) { + return($def[4]); + } + } + } + } +} diff --git a/mod/wiki/db/upgrade.php b/mod/wiki/db/upgrade.php index b594ca3f29c..b4a70e984f6 100644 --- a/mod/wiki/db/upgrade.php +++ b/mod/wiki/db/upgrade.php @@ -36,36 +36,6 @@ * */ -/** - * - * TODO LIST: - * - * 1. Add needed fields to wiki table. DONE - * 2. Rename other wiki tables. DONE - * 3. Create new wiki tables. DONE BUT NOT FINISHED, WATING FOR NEW TABLES - * 4. Move/Adapt/Transform configurations info to new structure - * 5. Migrate wiki entries to subwikis. DONE - * 6. Fill pages table with latest versions of every page. DONE - * 7. Migrate page history to new table (transforming formats). DONE, BUT STILL WORKING - * 8. Fill links table - * 9. Drop useless information - * - * ADITIONAL THINGS AFTER CHAT WITH ELOY: - * - * 1. addField is deprecated. DONE - * 2. Fix SQL error at block 3. DONE - * 3. Merge set_field_select with previous update sentence. DONE - * 4. Don't insert id fields on database (it won't work on mssql, oracle, pg). DONE. - * 5. Use upgrade_set_timeout function. - * 6. Use grafic of progess - * - * OTHER THINGS: - * - * 1. Use recordset instead of record when migrating historic - * 2. Select only usefull data on block 06 - * - */ - function xmldb_wiki_upgrade($oldversion) { global $CFG, $DB, $OUTPUT; @@ -149,9 +119,9 @@ function xmldb_wiki_upgrade($oldversion) { /** * Migrating wiki entries to new subwikis */ - $sql = "INSERT into {wiki_subwikis} (wikiid, groupid, userid) - SELECT DISTINCT e.wikiid, e.groupid, e.userid - FROM {wiki_entries_old} e"; + $sql = "INSERT INTO {wiki_subwikis} (wikiid, groupid, userid) + SELECT DISTINCT e.wikiid, e.groupid, e.userid + FROM {wiki_entries_old} e"; echo $OUTPUT->notification('Migrating old entries to new subwikis', 'notifysuccess'); $DB->execute($sql, array()); @@ -161,30 +131,39 @@ function xmldb_wiki_upgrade($oldversion) { // Step 5: Migrating pages if ($oldversion < 2010040105) { - /** - * Filling pages table with latest versions of every page. - * - * @TODO: Ensure that ALL versions of every page are always in database and - * they can be removed or cleaned. - * That fact could let us rewrite the subselect to execute a count(*) to avoid - * the order by and it would be much faster. - */ - $sql = "INSERT into {wiki_pages} (subwikiid, title, cachedcontent, timecreated, timemodified, userid, pageviews) - SELECT s.id, p.pagename, ?, p.created, p.lastmodified, p.userid, p.hits - FROM {wiki_pages_old} p - LEFT OUTER JOIN {wiki_entries_old} e ON e.id = p.wiki - LEFT OUTER JOIN {wiki_subwikis} s - ON s.wikiid = e.wikiid AND s.groupid = e.groupid AND s.userid = e.userid - WHERE p.version = ( - SELECT max(po.version) - FROM {wiki_pages_old} po - WHERE p.pagename = po.pagename and - p.wiki = po.wiki - )"; + // select all wiki pages + $sql = "SELECT s.id, p.pagename, p.created, p.lastmodified, p.userid, p.hits + FROM {wiki_pages_old} p + LEFT OUTER JOIN {wiki_entries_old} e ON e.id = p.wiki + LEFT OUTER JOIN {wiki_subwikis} s ON s.wikiid = e.wikiid AND s.groupid = e.groupid AND s.userid = e.userid + WHERE p.version = (SELECT max(po.version) + FROM {wiki_pages_old} po + WHERE p.pagename = po.pagename AND p.wiki = po.wiki)"; echo $OUTPUT->notification('Migrating old pages to new pages', 'notifysuccess'); - $DB->execute($sql, array('**reparse needed**')); + $records = $DB->get_recordset_sql($sql); + foreach ($records as $record) { + $page = new stdclass(); + $page->subwikiid = $record->id; + $page->title = $record->pagename; + $page->cachedcontent = '**reparse needed**'; + $page->timecreated = $record->created; + $page->timemodified = $record->lastmodified; + $page->userid = $record->userid; + $page->pageviews = $record->hits; + try { + // make sure there is no duplicated records exist + if (!$DB->record_exists('wiki_pages', array('subwikiid'=>$record->id, 'userid'=>$record->userid, 'title'=>$record->pagename))) { + $DB->insert_record('wiki_pages', $page); + } + } catch (dml_exception $e) { + // catch possible insert exception + debugging($e->getMessage()); + continue; + } + } + $records->close(); upgrade_mod_savepoint(true, 2010040105, 'wiki'); } @@ -295,22 +274,6 @@ function xmldb_wiki_upgrade($oldversion) { upgrade_mod_savepoint(true, 2010040109, 'wiki'); } - // TODO: Will hold the old tables so we will have chance to fix problems - // Will remove old tables once migrating 100% stable - // Step 10: delete old tables - if ($oldversion < 2010040120) { - //$tables = array('wiki_pages', 'wiki_locks', 'wiki_entries'); - - //foreach ($tables as $tablename) { - //$table = new xmldb_table($tablename . '_old'); - //if ($dbman->table_exists($table)) { - //$dbman->drop_table($table); - //} - //} - //echo $OUTPUT->notification('Droping old tables', 'notifysuccess'); - //upgrade_mod_savepoint(true, 2010040120, 'wiki'); - } - if ($oldversion < 2010080201) { $sql = "UPDATE {comments} @@ -360,5 +323,21 @@ function xmldb_wiki_upgrade($oldversion) { upgrade_mod_savepoint(true, 2010102800, 'wiki'); } + // TODO: Will hold the old tables so we will have chance to fix problems + // Will remove old tables once migrating 100% stable + // Step 10: delete old tables + //if ($oldversion < 2011000000) { + //$tables = array('wiki_pages', 'wiki_locks', 'wiki_entries'); + + //foreach ($tables as $tablename) { + //$table = new xmldb_table($tablename . '_old'); + //if ($dbman->table_exists($table)) { + //$dbman->drop_table($table); + //} + //} + //echo $OUTPUT->notification('Droping old tables', 'notifysuccess'); + //upgrade_mod_savepoint(true, 2011000000, 'wiki'); + //} + return true; } diff --git a/mod/wiki/db/upgradelib.php b/mod/wiki/db/upgradelib.php index d4a961ceb86..1fd3d44fc37 100644 --- a/mod/wiki/db/upgradelib.php +++ b/mod/wiki/db/upgradelib.php @@ -202,23 +202,52 @@ function wiki_upgrade_install_20_tables() { */ function wiki_upgrade_migrate_versions() { global $DB, $CFG, $OUTPUT; - upgrade_set_timeout(); require_once($CFG->dirroot . '/mod/wiki/db/migration/lib.php'); - $sql = "SELECT po.id as oldpage_id, po.pagename as oldpage_pagename, po.version, po.flags, po.content, po.author, po.userid as oldpage_userid, po.created, po.lastmodified, po.refs, po.meta, po.hits, po.wiki, - p.id as newpage_id, p.subwikiid, p.title, p.cachedcontent, p.timecreated, p.timemodified as newpage_timemodified, p.timerendered, p.userid as newpage_userid, p.pageviews, p.readonly, - e.id as entry_id, e.wikiid, e.course as entrycourse, e.groupid, e.userid as entry_userid, e.pagename as entry_pagename, e.timemodified as entry_timemodified, - w.id as wiki_id, w.course as wiki_course, w.name, w.summary as summary, w.pagename as wiki_pagename, w.wtype, w.ewikiprinttitle, w.htmlmode, w.ewikiacceptbinary, w.disablecamelcase, w.setpageflags, w.strippages, w.removepages, w.revertchanges, w.initialcontent, w.timemodified as wiki_timemodified - FROM {wiki_pages_old} po LEFT OUTER JOIN {wiki_entries_old} e - ON e.id = po.wiki - LEFT OUTER JOIN {wiki} w - ON w.id = e.wikiid - LEFT OUTER JOIN {wiki_subwikis} s - ON e.groupid = s.groupid AND e.wikiid = s.wikiid AND e.userid = s.userid - LEFT OUTER JOIN {wiki_pages} p - ON po.pagename = p.title AND p.subwikiid = s.id"; + // need to move the binary data in db + $fs = get_file_storage(); + // select all wiki pages history + $sql = "SELECT po.id AS oldpage_id, po.pagename AS oldpage_pagename, po.version, po.flags, + po.content, po.author, po.userid AS oldpage_userid, po.created, po.lastmodified, po.refs, po.meta, po.hits, po.wiki, + p.id AS newpage_id, p.subwikiid, p.title, p.cachedcontent, p.timecreated, p.timemodified AS newpage_timemodified, + p.timerendered, p.userid AS newpage_userid, p.pageviews, p.readonly, e.id AS entry_id, e.wikiid, e.course AS entrycourse, + e.groupid, e.userid AS entry_userid, e.pagename AS entry_pagename, e.timemodified AS entry_timemodified, + w.id AS wiki_id, w.course AS wiki_course, w.name, w.summary AS summary, w.pagename AS wiki_pagename, w.wtype, + w.ewikiprinttitle, w.htmlmode, w.ewikiacceptbinary, w.disablecamelcase, w.setpageflags, w.strippages, w.removepages, + w.revertchanges, w.initialcontent, w.timemodified AS wiki_timemodified, + cm.id AS cmid + FROM {wiki_pages_old} po + LEFT OUTER JOIN {wiki_entries_old} e ON e.id = po.wiki + LEFT OUTER JOIN {wiki} w ON w.id = e.wikiid + LEFT OUTER JOIN {wiki_subwikis} s ON e.groupid = s.groupid AND e.wikiid = s.wikiid AND e.userid = s.userid + LEFT OUTER JOIN {wiki_pages} p ON po.pagename = p.title AND p.subwikiid = s.id + JOIN {modules} m ON m.name = 'wiki' + JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = w.id)"; + $pagesinfo = $DB->get_recordset_sql($sql, array()); foreach ($pagesinfo as $pageinfo) { + upgrade_set_timeout(); + + $mimetype = ewiki_mime_magic($pageinfo->content); + if (!empty($mimetype)) { + // if mimetype is not empty, means this is a file stored in db + $context = get_context_instance(CONTEXT_MODULE, $pageinfo->cmid); + // clean up file name + $filename = clean_param($pageinfo->oldpage_pagename, PARAM_FILE); + $filerecord = array('contextid' => $context->id, + 'component' => 'mod_wiki', + 'filearea' => 'attachments', + 'itemid' => $pageinfo->subwikiid, + 'filepath' => '/', + 'filename' => $filename, + 'userid' => $pageinfo->oldpage_userid); + if (!$fs->file_exists($context->id, 'mod_wiki', 'attachments', $pageinfo->subwikiid, '/', $pageinfo->pagename)) { + $storedfile = $fs->create_file_from_string($filerecord, $pageinfo->content); + } + + // replace page content to a link point to the file + $pageinfo->content = "$pageinfo->oldpage_pagename"; + } $oldpage = new StdClass(); $oldpage->id = $pageinfo->oldpage_id; @@ -276,8 +305,9 @@ function wiki_upgrade_migrate_versions() { $version = new StdClass(); $version->pageid = $page->id; + // convert wiki content to html format $version->content = wiki_ewiki_2_html($entry, $oldpage, $wiki); - $version->contentformat = "html"; + $version->contentformat = 'html'; $version->version = $oldpage->version; $version->timecreated = $oldpage->lastmodified; $version->userid = $oldpage->userid; @@ -292,14 +322,14 @@ function wiki_upgrade_migrate_versions() { $version->version = 1; $version->content = $content; $DB->insert_record('wiki_versions', $version); - } catch (Exception $e) { - echo $OUTPUT->notification('Cannot insert this record, page id: ' . $page->id); + } catch (dml_exception $e) { + debugging($e->getMessage()); } } else { try { $DB->insert_record('wiki_versions', $version); - } catch (Exception $e) { - echo $OUTPUT->notification('Cannot insert this record, page id: ' . $page->id); + } catch (dml_exception $e) { + debugging($e->getMessage()); } } } diff --git a/mod/wiki/locallib.php b/mod/wiki/locallib.php index 6f077953016..2ff2741b5ec 100644 --- a/mod/wiki/locallib.php +++ b/mod/wiki/locallib.php @@ -261,6 +261,9 @@ function wiki_refresh_cachedcontent($page, $newcontent = null) { global $DB; $version = wiki_get_current_version($page->id); + if (empty($version)) { + return null; + } if (!isset($newcontent)) { $newcontent = $version->content; } @@ -299,7 +302,11 @@ function wiki_refresh_page_links($page, $links) { $newlink->topageid = $linkinfo['pageid']; } - $DB->insert_record('wiki_links', $newlink); + try { + $DB->insert_record('wiki_links', $newlink); + } catch (dml_exception $e) { + debugging($e->getMessage()); + } } }