function ouwiki_restore_mods($mod, $restore)
{
    global $CFG;
    $status = true;
    //Get record from backup_ids
    if ($data = backup_getid($restore->backup_unique_code, $mod->modtype, $mod->id)) {
        try {
            if (!defined('RESTORE_SILENTLY')) {
                $name = $data->info['MOD']['#']['NAME']['0']['#'];
                echo "<li>" . get_string('modulename', 'ouwiki') . ' "' . htmlspecialchars($name) . '"</li>';
            }
            // Boom. Now try restoring!
            $xml = $data->info['MOD']['#'];
            $userdata = restore_userdata_selected($restore, 'ouwiki', $mod->id);
            $ouwiki = new stdClass();
            $ouwiki->course = $restore->course_id;
            $ouwiki->name = addslashes($xml['NAME'][0]['#']);
            $ouwiki->subwikis = $xml['SUBWIKIS'][0]['#'];
            if (isset($xml['TIMEOUT'][0]['#'])) {
                $ouwiki->timeout = $xml['TIMEOUT'][0]['#'];
            }
            if (isset($xml['TEMPLATE'][0]['#'])) {
                $ouwiki->template = addslashes($xml['TEMPLATE'][0]['#']);
            }
            if (isset($xml['SUMMARY'][0]['#'])) {
                $ouwiki->summary = addslashes($xml['SUMMARY'][0]['#']);
            }
            if (isset($xml['EDITBEGIN'][0]['#'])) {
                $ouwiki->editbegin = addslashes($xml['EDITBEGIN'][0]['#']);
            }
            if (isset($xml['EDITEND'][0]['#'])) {
                $ouwiki->editend = addslashes($xml['EDITEND'][0]['#']);
            }
            if (isset($xml['COMPLETIONPAGES'][0]['#'])) {
                $ouwiki->completionpages = addslashes($xml['COMPLETIONPAGES'][0]['#']);
            }
            if (isset($xml['COMPLETIONEDITS'][0]['#'])) {
                $ouwiki->completionedits = addslashes($xml['COMPLETIONEDITS'][0]['#']);
            }
            if (isset($xml['COMMENTING'][0]['#'])) {
                $ouwiki->commenting = addslashes($xml['COMMENTING'][0]['#']);
            }
            if (!($ouwiki->id = insert_record('ouwiki', $ouwiki))) {
                throw new Exception('Error creating ouwiki instance');
            }
            backup_putid($restore->backup_unique_code, $mod->modtype, $mod->id, $ouwiki->id);
            if (isset($xml['SUBS'][0]['#']['SUBWIKI'])) {
                foreach ($xml['SUBS'][0]['#']['SUBWIKI'] as $xml_sub) {
                    ouwiki_restore_subwiki($restore, $xml_sub['#'], $ouwiki, $userdata);
                }
            }
            xml_backup::restore_module_files($restore->backup_unique_code, $restore->course_id, 'ouwiki', $mod->id);
            $basepath = $CFG->dataroot . '/' . $restore->course_id . '/moddata/ouwiki';
            rename($basepath . '/' . $mod->id, $basepath . '/' . $ouwiki->id);
        } catch (Exception $e) {
            ouwiki_handle_backup_exception($e, 'restore');
            $status = false;
        }
    }
    return $status;
}
function ouwiki_backup_one_mod($bf, $preferences, $ouwiki)
{
    global $CFG;
    if (is_numeric($ouwiki)) {
        $ouwiki = get_record('ouwiki', 'id', $ouwiki);
    }
    try {
        $xb = new xml_backup($bf, $preferences, 3);
        $xb->tag_start('MOD');
        // Required bits
        $xb->tag_full('ID', $ouwiki->id);
        $xb->tag_full('MODTYPE', 'ouwiki');
        $xb->tag_full('NAME', $ouwiki->name);
        // Backup versioning
        require dirname(__FILE__) . '/version.php';
        $xb->tag_full('OUWIKI_VERSION', $module->version);
        // Wiki-specific
        $xb->tag_full('SUBWIKIS', $ouwiki->subwikis);
        $userdata = backup_userdata_selected($preferences, 'ouwiki', $ouwiki->id);
        $xb->tag_full_notnull('TIMEOUT', $ouwiki->timeout);
        if ($ouwiki->template) {
            // Template setting and actual file
            $xb->tag_full('TEMPLATE', $ouwiki->template);
            $xb->copy_module_file('ouwiki', $ouwiki->id . '/' . $ouwiki->template);
        }
        $xb->tag_full_notnull('SUMMARY', $ouwiki->summary);
        $xb->tag_full_notnull('EDITBEGIN', $ouwiki->editbegin);
        $xb->tag_full_notnull('EDITEND', $ouwiki->editend);
        $xb->tag_full('COMPLETIONPAGES', $ouwiki->completionpages);
        $xb->tag_full('COMPLETIONEDITS', $ouwiki->completionedits);
        $xb->tag_full('COMMENTING', $ouwiki->commenting);
        // Now do the actual subwikis
        $xb->tag_start('SUBS');
        // not SUBWIKIS because that name already used
        // We only back up content when 'user data' is turned on
        if ($userdata) {
            $subwikis = ouwiki_get_record_array('subwikis', 'wikiid', $ouwiki->id);
            foreach ($subwikis as $subwiki) {
                ouwiki_backup_subwiki($xb, $subwiki, $userdata);
            }
        }
        $xb->tag_end('SUBS');
        $xb->tag_end('MOD');
        return true;
    } catch (Exception $e) {
        ouwiki_handle_backup_exception($e);
        return false;
    }
}
function forumng_backup_one_mod($bf, $preferences, $forumng)
{
    global $CFG;
    try {
        if (is_numeric($forumng)) {
            $forumng = forum_utils::get_record('forumng', 'id', $forumng);
        }
        $xb = new xml_backup($bf, $preferences, 3);
        $xb->tag_start('MOD');
        // Required bits
        $xb->tag_full('ID', $forumng->id);
        $xb->tag_full('MODTYPE', 'forumng');
        $xb->tag_full('NAME', $forumng->name);
        // Backup versioning
        require dirname(__FILE__) . '/version.php';
        $xb->tag_full('FORUMNG_VERSION', $module->version);
        // Are we doing user data?
        $userdata = backup_userdata_selected($preferences, 'forumng', $forumng->id);
        // ForumNG-specific
        $xb->tag_full_notnull('TYPE', $forumng->type);
        $xb->tag_full_notnull('INTRO', $forumng->intro);
        $xb->tag_full('RATINGSCALE', $forumng->ratingscale);
        $xb->tag_full('RATINGFROM', $forumng->ratingfrom);
        $xb->tag_full('RATINGUNTIL', $forumng->ratinguntil);
        $xb->tag_full('RATINGTHRESHOLD', $forumng->ratingthreshold);
        $xb->tag_full('GRADING', $forumng->grading);
        $xb->tag_full('ATTACHMENTMAXBYTES', $forumng->attachmentmaxbytes);
        $xb->tag_full('REPORTINGEMAIL', $forumng->reportingemail);
        $xb->tag_full('SUBSCRIPTION', $forumng->subscription);
        $xb->tag_full('FEEDTYPE', $forumng->feedtype);
        $xb->tag_full('FEEDITEMS', $forumng->feeditems);
        $xb->tag_full('MAXPOSTSPERIOD', $forumng->maxpostsperiod);
        $xb->tag_full('MAXPOSTSBLOCK', $forumng->maxpostsblock);
        $xb->tag_full('POSTINGFROM', $forumng->postingfrom);
        $xb->tag_full('POSTINGUNTIL', $forumng->postinguntil);
        $xb->tag_full_notnull('TYPEDATA', $forumng->typedata);
        $xb->tag_full('MAGICNUMBER', $forumng->magicnumber);
        $xb->tag_full('COMPLETIONDISCUSSIONS', $forumng->completiondiscussions);
        $xb->tag_full('COMPLETIONREPLIES', $forumng->completionreplies);
        $xb->tag_full('COMPLETIONPOSTS', $forumng->completionposts);
        $xb->tag_full('REMOVEAFTER', $forumng->removeafter);
        $xb->tag_full('REMOVETO', $forumng->removeto);
        $xb->tag_full('SHARED', $forumng->shared);
        // When this is a clone forum, we store the idnumber of the original
        // forum so that it can be found afterward; this makes sense rather
        // than using the normal cmid mapping because it might be on a different
        // course or something, also idnumber is shown in the interface.
        if ($forumng->originalcmid) {
            $idnumber = get_field('course_modules', 'idnumber', 'id', $forumng->originalcmid);
            if ($idnumber) {
                $xb->tag_full('ORIGINALCMIDNUMBER', $idnumber);
            }
        }
        // We only back up most content when 'user data' is turned on
        if ($userdata) {
            $xb->tag_start('DISCUSSIONS');
            $rs = forum_utils::get_recordset('forumng_discussions', 'forumid', $forumng->id);
            while ($discussion = rs_fetch_next_record($rs)) {
                forumng_backup_discussion($xb, $discussion);
            }
            rs_close($rs);
            $xb->tag_end('DISCUSSIONS');
            $xb->tag_start('SUBSCRIPTIONS');
            $rs = forum_utils::get_recordset('forumng_subscriptions', 'forumid', $forumng->id);
            while ($subscription = rs_fetch_next_record($rs)) {
                forumng_backup_subscription($xb, $subscription);
            }
            rs_close($rs);
            $xb->tag_end('SUBSCRIPTIONS');
            forumng_backup_files($bf, $preferences, $forumng->id);
        }
        $xb->tag_end('MOD');
        return true;
    } catch (Exception $e) {
        forum_utils::handle_backup_exception($e);
        return false;
    }
}
function forumng_restore_mods($mod, $restore)
{
    global $CFG;
    $status = true;
    //Get record from backup_ids
    $forumid = 0;
    if ($data = backup_getid($restore->backup_unique_code, $mod->modtype, $mod->id)) {
        try {
            if (!defined('RESTORE_SILENTLY')) {
                $name = $data->info['MOD']['#']['NAME']['0']['#'];
                echo "<li>" . get_string('modulename', 'forumng') . ' "' . htmlspecialchars($name) . '"</li>';
            }
            // Boom. Now try restoring!
            $xml = $data->info['MOD']['#'];
            $userdata = restore_userdata_selected($restore, 'forumng', $mod->id);
            $forumng = new stdClass();
            $forumng->course = $restore->course_id;
            $forumng->name = addslashes($xml['NAME'][0]['#']);
            // ForumNG-specific data
            if (isset($xml['TYPE'][0]['#'])) {
                $forumng->type = backup_todb($xml['TYPE'][0]['#']);
            }
            if (isset($xml['INTRO'][0]['#'])) {
                $forumng->intro = backup_todb($xml['INTRO'][0]['#']);
            } else {
                $forumng->intro = null;
            }
            $forumng->ratingscale = $xml['RATINGSCALE'][0]['#'];
            $forumng->ratingfrom = $xml['RATINGFROM'][0]['#'];
            $forumng->ratinguntil = $xml['RATINGUNTIL'][0]['#'];
            $forumng->ratingthreshold = $xml['RATINGTHRESHOLD'][0]['#'];
            $forumng->grading = $xml['GRADING'][0]['#'];
            $forumng->attachmentmaxbytes = $xml['ATTACHMENTMAXBYTES'][0]['#'];
            if (isset($xml['REPORTINGEMAIL'][0]['#'])) {
                $forumng->reportingemail = backup_todb($xml['REPORTINGEMAIL'][0]['#']);
            }
            $forumng->subscription = $xml['SUBSCRIPTION'][0]['#'];
            $forumng->feedtype = $xml['FEEDTYPE'][0]['#'];
            $forumng->feeditems = $xml['FEEDITEMS'][0]['#'];
            $forumng->maxpostsperiod = $xml['MAXPOSTSPERIOD'][0]['#'];
            $forumng->maxpostsblock = $xml['MAXPOSTSBLOCK'][0]['#'];
            $forumng->postingfrom = $xml['POSTINGFROM'][0]['#'];
            $forumng->postinguntil = $xml['POSTINGUNTIL'][0]['#'];
            if (isset($xml['TYPEDATA'][0]['#'])) {
                $forumng->typedata = backup_todb($xml['TYPEDATA'][0]['#']);
            }
            $forumng->magicnumber = $xml['MAGICNUMBER'][0]['#'];
            $forumng->completiondiscussions = $xml['COMPLETIONDISCUSSIONS'][0]['#'];
            $forumng->completionreplies = $xml['COMPLETIONREPLIES'][0]['#'];
            $forumng->completionposts = $xml['COMPLETIONPOSTS'][0]['#'];
            if (isset($xml['REMOVEAFTER'][0]['#'])) {
                $forumng->removeafter = $xml['REMOVEAFTER'][0]['#'];
            }
            if (isset($xml['REMOVETO'][0]['#'])) {
                $forumng->removeto = backup_todb($xml['REMOVETO'][0]['#']);
            }
            if (isset($xml['SHARED'][0]['#'])) {
                $forumng->shared = $xml['SHARED'][0]['#'];
            }
            // To protect the forum intro field from molestation if some idiot
            // sets it to a weird value...
            if (preg_match('~%%CMIDNUMBER:[^%]+%%$~', $forumng->intro)) {
                $forumng->intro .= '%%REMOVETHIS%%';
            }
            if (isset($xml['ORIGINALCMIDNUMBER'][0]['#'])) {
                if ($forumng->intro === null) {
                    $forumng->intro = '';
                }
                // This is a bit of a hack, but we need to wait until everything
                // is restored, and it is a text value; so temporarily, add it
                // to the end of the intro field.
                $forumng->intro .= '%%CMIDNUMBER:' . backup_todb($xml['ORIGINALCMIDNUMBER'][0]['#']) . '%%';
            }
            // Insert main record
            if (!($forumng->id = insert_record('forumng', $forumng))) {
                throw new forum_exception('Error creating forumng instance');
            }
            $forumid = $forumng->id;
            backup_putid($restore->backup_unique_code, $mod->modtype, $mod->id, $forumng->id);
            if ($userdata) {
                if (isset($xml['DISCUSSIONS'][0]['#']['DISCUSSION'])) {
                    foreach ($xml['DISCUSSIONS'][0]['#']['DISCUSSION'] as $xml_sub) {
                        forumng_restore_discussion($restore, $xml_sub['#'], $forumng);
                    }
                }
                if (isset($xml['SUBSCRIPTIONS'][0]['#']['SUBSCRIPTION'])) {
                    foreach ($xml['SUBSCRIPTIONS'][0]['#']['SUBSCRIPTION'] as $xml_sub) {
                        forumng_restore_subscription($restore, $xml_sub['#'], $forumng);
                    }
                }
                // Attachments
                xml_backup::restore_module_files($restore->backup_unique_code, $restore->course_id, 'forumng', $mod->id);
                $basepath = $CFG->dataroot . '/' . $restore->course_id . '/moddata/forumng';
                rename($basepath . '/' . $mod->id, $basepath . '/' . $forumng->id);
            }
        } catch (Exception $e) {
            // Clean out any partially-created data
            try {
                forum_utils::execute_sql("\nDELETE FROM {$CFG->prefix}forumng_ratings\nWHERE postid IN (\nSELECT fp.id\nFROM\n    {$CFG->prefix}forumng_discussions fd\n    INNER JOIN {$CFG->prefix}forumng_posts fp ON fp.discussionid = fd.id\nWHERE\n    fd.forumid = {$forumid}\n)");
                $discussionquery = "\nWHERE discussionid IN (\nSELECT id FROM {$CFG->prefix}forumng_discussions WHERE forumid={$forumid})";
                forum_utils::execute_sql("DELETE FROM {$CFG->prefix}forumng_posts {$discussionquery}");
                forum_utils::execute_sql("DELETE FROM {$CFG->prefix}forumng_read {$discussionquery}");
                forum_utils::delete_records('forumng_subscriptions', 'forumid', $forumid);
                forum_utils::delete_records('forumng_discussions', 'forumid', $forumid);
                forum_utils::delete_records('forumng', 'id', $forumid);
            } catch (Exception $e) {
                debugging('Error occurred when trying to clean partial data');
            }
            forum_utils::handle_backup_exception($e, 'restore');
            $status = false;
        }
    }
    return $status;
}