# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: moodle/lang/en_utf8/data.php
--- moodle/lang/en_utf8/data.php Base (1.85)
+++ moodle/lang/en_utf8/data.php Locally Modified (Based On 1.85)
@@ -81,6 +81,7 @@
 $string['descending'] = 'Descending';
 $string['directorynotapreset'] = '$a->directory Not a preset: missing files: $a->missing_files';
 $string['download'] = 'Download';
+$string['duplicatepresetname'] = 'The preset name you selected has already been used please choose a unique name';
 $string['edit'] = 'Edit';
 $string['editcomment'] = 'Edit comment';
 $string['editentry'] = 'Edit entry';
@@ -219,6 +220,8 @@
 $string['portfolionotfile'] = 'Export to a portfolio rather than a file (csv and leap2a only)';
 $string['presetinfo'] = 'Saving as a preset will publish this template. Other users may be able to use it in their databases.';
 $string['presets'] = 'Presets';
+$string['presetname'] = 'Preset name';
+$string['presetnamerequired'] = 'You must enter a unique name for the new preset';
 $string['radiobutton'] = 'Radio buttons';
 $string['rate'] = 'Rate';
 $string['rating'] = 'Rating';
@@ -258,6 +261,7 @@
 $string['single'] = 'View single';
 $string['singletemplate'] = 'Single template';
 $string['showall'] = 'Show all entries';
+$string['successpresetuploaded'] = 'Preset successfully uploaded and saved';
 $string['teachersandstudents'] = '$a->teachers and $a->students';
 $string['templates'] = 'Templates';
 $string['templatesaved'] = 'Template saved';
@@ -272,6 +276,7 @@
 $string['updatefield'] = 'Update an existing field';
 $string['uploadfile'] = 'Upload file';
 $string['uploadrecords'] = 'Upload entries from a file';
+$string['uploadanewpreset'] = 'Upload a preset';
 $string['url'] = 'Url';
 $string['usestandard'] = 'Use a preset';
 $string['viewfromdate'] = 'Viewable from';
Index: moodle/mod/data/field.php
--- moodle/mod/data/field.php Base (1.48)
+++ moodle/mod/data/field.php Locally Modified (Based On 1.48)
@@ -91,6 +91,8 @@
 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 require_capability('mod/data:managetemplates', $context);
 
+$renderer = $PAGE->get_renderer('mod_data');
+
 /************************************
  *        Data Processing           *
  ***********************************/
@@ -202,7 +204,7 @@
 
             } else {
 
-                data_print_header($course,$cm,$data, false);
+                echo $renderer->header($course,$cm,$data, false);
 
                 // Print confirmation message.
                 $field = data_get_field_from_id($fid, $data);
@@ -250,19 +252,19 @@
 $PAGE->set_pagetype('mod-data-field-' . $newtype);
 $PAGE->navbar->add(get_string('fields', 'data'));
 if (($mode == 'new') && (!empty($newtype)) && confirm_sesskey()) {          ///  Adding a new field
-    data_print_header($course, $cm, $data,'fields');
+    echo $renderer->header($course,$cm,$data, 'fields');
 
     $field = data_get_field_new($newtype, $data);
     $field->display_edit_field();
 
 } else if ($mode == 'display' && confirm_sesskey()) { /// Display/edit existing field
-    data_print_header($course, $cm, $data,'fields');
+    echo $renderer->header($course,$cm,$data, 'fields');
 
     $field = data_get_field_from_id($fid, $data);
     $field->display_edit_field();
 
 } else {                                              /// Display the main listing of all fields
-    data_print_header($course, $cm, $data,'fields');
+    echo $renderer->header($course,$cm,$data, 'fields');
 
     if (!$DB->record_exists('data_fields', array('dataid'=>$data->id))) {
         echo $OUTPUT->notification(get_string('nofieldindatabase','data'));  // nothing in database
Index: moodle/mod/data/lib.php
--- moodle/mod/data/lib.php Base (1.259)
+++ moodle/mod/data/lib.php Locally Modified (Based On 1.259)
@@ -36,6 +36,13 @@
 // Using the mod/data capability "viewalluserpresets" existing in Moodle 1.9.x.
 // In Moodle >= 2, new roles may be introduced and used instead.
 
+/** Used to identify a predefined preset that exists in /mod/data/preset/ */
+define('DATA_PRESET_PREDEFINED', 0);
+/** Used to identify a saved preset that exists in a file area */
+define('DATA_PRESET_SAVED', 1);
+/** The file area in which to store presets */
+define('DATA_PRESET_FILEAREA', 'mod_data_preset');
+
 /**
  * @package   mod-data
  * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
@@ -1116,7 +1123,6 @@
 function data_grade_item_delete($data) {
     global $CFG;
     require_once($CFG->libdir.'/gradelib.php');
-
     return grade_update('mod/data', $data->course, 'mod', 'data', $data->id, 0, NULL, array('deleted'=>1));
 }
 
@@ -1725,16 +1731,10 @@
 function data_convert_arrays_to_strings(&$fieldinput) {
     foreach ($fieldinput as $key => $val) {
         if (is_array($val)) {
-            $str = '';
-            foreach ($val as $inner) {
-                $str .= $inner . ',';
+            $fieldinput->$key = join(',', $val);
             }
-            $str = substr($str, 0, -1);
-
-            $fieldinput->$key = $str;
         }
     }
-}
 
 
 /**
@@ -1883,14 +1883,11 @@
  * Returns the best name to show for a preset
  *
  * @param string $shortname
- * @param  string $path
  * @return string
  */
-function data_preset_name($shortname, $path) {
-
+function data_preset_name($shortname) {
     // We are looking inside the preset itself as a first choice, but also in normal data directory
     $string = get_string('modulename', 'datapreset_'.$shortname);
-
     if (substr($string, 0, 1) == '[') {
         return $shortname;
     } else {
@@ -1913,13 +1910,13 @@
     if ($dirs = get_list_of_plugins('mod/data/preset')) {
         foreach ($dirs as $dir) {
             $fulldir = $CFG->dirroot.'/mod/data/preset/'.$dir;
-
             if (is_directory_a_preset($fulldir)) {
                 $preset = new object;
                 $preset->path = $fulldir;
                 $preset->userid = 0;
                 $preset->shortname = $dir;
                 $preset->name = data_preset_name($dir, $fulldir);
+                $preset->type = DATA_PRESET_PREDEFINED;
                 if (file_exists($fulldir.'/screenshot.jpg')) {
                     $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg';
                 } else if (file_exists($fulldir.'/screenshot.png')) {
@@ -1932,79 +1929,29 @@
         }
     }
 
-    if ($userids = get_list_of_plugins('data/preset', '', $CFG->dataroot)) {
-        foreach ($userids as $userid) {
-            $fulldir = $CFG->dataroot.'/data/preset/'.$userid;
-
-            if ($userid == 0 || $USER->id == $userid || has_capability('mod/data:viewalluserpresets', $context)) {
-
-                if ($dirs = get_list_of_plugins('data/preset/'.$userid, '', $CFG->dataroot)) {
-                    foreach ($dirs as $dir) {
-                        $fulldir = $CFG->dataroot.'/data/preset/'.$userid.'/'.$dir;
-
-                        if (is_directory_a_preset($fulldir)) {
-                            $preset = new object;
-                            $preset->path = $fulldir;
-                            $preset->userid = $userid;
-                            $preset->shortname = $dir;
-                            $preset->name = data_preset_name($dir, $fulldir);
-                            if (file_exists($fulldir.'/screenshot.jpg')) {
-                                $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.jpg';
-                            } else if (file_exists($fulldir.'/screenshot.png')) {
-                                $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.png';
-                            } else if (file_exists($fulldir.'/screenshot.gif')) {
-                                $preset->screenshot = $CFG->wwwroot.'/mod/data/preset/'.$dir.'/screenshot.gif';
-                            }
+    $fs = get_file_storage();
+    $directory = $fs->get_area_tree($context->id, DATA_PRESET_FILEAREA, false);
+    $manageall = has_capability('mod/data:viewalluserpresets', $context);   
+    foreach ($directory['subdirs'] as $subdir) {
+        if (is_array($subdir) && array_key_exists('dirname', $subdir) && $subdir['dirfile']->is_directory() && ($manageall || $subdir['dirfile']->get_itemid() == 0 || $subdir['dirfile']->get_itemid() == $USER->id)) {
+            $preset = new stdClass;
+            $preset->path = $subdir['dirfile']->get_filepath();
+            $preset->userid = $subdir['dirfile']->get_itemid();
+            $preset->shortname = $subdir['dirname'];
+            $preset->name = data_preset_name($preset->shortname);
+            $preset->type = DATA_PRESET_SAVED;
+            $preset->directory = $subdir['dirfile'];
+            $preset->files = $subdir['files'];
                             $presets[] = $preset;
                         }
                     }
-                }
-            }
-        }
-    }
 
     return $presets;
 }
 
 /**
  * @global object
- * @global string
- * @global string
- * @param object $course
- * @param object $cm
  * @param object $data
- * @param string $currenttab
- */
-function data_print_header($course, $cm, $data, $currenttab='') {
-
-    global $CFG, $displaynoticegood, $displaynoticebad, $OUTPUT, $PAGE;
-
-    $PAGE->set_title($data->name);
-    echo $OUTPUT->header();
-    echo $OUTPUT->heading(format_string($data->name));
-
-// Groups needed for Add entry tab
-    $currentgroup = groups_get_activity_group($cm);
-    $groupmode = groups_get_activity_groupmode($cm);
-
-    // Print the tabs
-
-    if ($currenttab) {
-        include('tabs.php');
-    }
-
-    // Print any notices
-
-    if (!empty($displaynoticegood)) {
-        echo $OUTPUT->notification($displaynoticegood, 'notifysuccess');    // good (usually green)
-    } else if (!empty($displaynoticebad)) {
-        echo $OUTPUT->notification($displaynoticebad);                     // bad (usuually red)
-    }
-}
-
-/**
- * @global object
- * @param object $data
  * @param mixed $currentgroup
  * @param int $groupmode
  * @return bool
@@ -2058,321 +2005,8 @@
 }
 
 /**
- * @return bool
- */
-function clean_preset($folder) {
-    $status = @unlink($folder.'/singletemplate.html') &&
-              @unlink($folder.'/listtemplate.html') &&
-              @unlink($folder.'/listtemplateheader.html') &&
-              @unlink($folder.'/listtemplatefooter.html') &&
-              @unlink($folder.'/addtemplate.html') &&
-              @unlink($folder.'/rsstemplate.html') &&
-              @unlink($folder.'/rsstitletemplate.html') &&
-              @unlink($folder.'/csstemplate.css') &&
-              @unlink($folder.'/jstemplate.js') &&
-              @unlink($folder.'/preset.xml');
-
-    // optional
-    @unlink($folder.'/asearchtemplate.html');
-
-    return $status;
-}
-
-/**
- * @package   mod-data
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class PresetImporter {
-    /**
      * @global object
-     * @param object $course
-     * @param object $cm
-     * @param object $data
-     * @param int $userid
-     * @param string $shortname
-     */
-    function PresetImporter($course, $cm, $data, $userid, $shortname) {
-        global $CFG;
-        $this->course = $course;
-        $this->cm = $cm;
-        $this->data = $data;
-        $this->userid = $userid;
-        $this->shortname = $shortname;
-        $this->folder = data_preset_path($course, $userid, $shortname);
-    }
-    /**
      * @global object
-     * @global object
-     * @return array
-     */
-    function get_settings() {
-        global $CFG, $DB;
-
-        if (!is_directory_a_preset($this->folder)) {
-            print_error('invalidpreset', 'data', '', $this->userid.'/'.$this->shortname);
-        }
-
-        /* Grab XML */
-        $presetxml = file_get_contents($this->folder.'/preset.xml');
-        $parsedxml = xmlize($presetxml, 0);
-
-        $allowed_settings = array('intro', 'comments', 'requiredentries', 'requiredentriestoview',
-                                  'maxentries', 'rssarticles', 'approval', 'defaultsortdir', 'defaultsort');
-
-        /* First, do settings. Put in user friendly array. */
-        $settingsarray = $parsedxml['preset']['#']['settings'][0]['#'];
-        $settings = new StdClass();
-
-        foreach ($settingsarray as $setting => $value) {
-            if (!is_array($value)) {
-                continue;
-            }
-            if (!in_array($setting, $allowed_settings)) {
-                // unsupported setting
-                continue;
-            }
-            $settings->$setting = $value[0]['#'];
-        }
-
-        /* Now work out fields to user friendly array */
-        $fieldsarray = $parsedxml['preset']['#']['field'];
-        $fields = array();
-        foreach ($fieldsarray as $field) {
-            if (!is_array($field)) {
-                continue;
-            }
-            $f = new StdClass();
-            foreach ($field['#'] as $param => $value) {
-                if (!is_array($value)) {
-                    continue;
-                }
-                $f->$param = $value[0]['#'];
-            }
-            $f->dataid = $this->data->id;
-            $f->type = clean_param($f->type, PARAM_ALPHA);
-            $fields[] = $f;
-        }
-        /* Now add the HTML templates to the settings array so we can update d */
-        $settings->singletemplate     = file_get_contents($this->folder."/singletemplate.html");
-        $settings->listtemplate       = file_get_contents($this->folder."/listtemplate.html");
-        $settings->listtemplateheader = file_get_contents($this->folder."/listtemplateheader.html");
-        $settings->listtemplatefooter = file_get_contents($this->folder."/listtemplatefooter.html");
-        $settings->addtemplate        = file_get_contents($this->folder."/addtemplate.html");
-        $settings->rsstemplate        = file_get_contents($this->folder."/rsstemplate.html");
-        $settings->rsstitletemplate   = file_get_contents($this->folder."/rsstitletemplate.html");
-        $settings->csstemplate        = file_get_contents($this->folder."/csstemplate.css");
-        $settings->jstemplate         = file_get_contents($this->folder."/jstemplate.js");
-
-        //optional
-        if (file_exists($this->folder."/asearchtemplate.html")) {
-            $settings->asearchtemplate = file_get_contents($this->folder."/asearchtemplate.html");
-        } else {
-            $settings->asearchtemplate = NULL;
-        }
-
-        $settings->instance = $this->data->id;
-
-        /* Now we look at the current structure (if any) to work out whether we need to clear db
-           or save the data */
-        if (!$currentfields = $DB->get_records('data_fields', array('dataid'=>$this->data->id))) {
-            $currentfields = array();
-        }
-
-        return array($settings, $fields, $currentfields);
-    }
-
-    /**
-     *
-     */
-    function import_options() {
-        global $OUTPUT;
-        if (!confirm_sesskey()) {
-            print_error('invalidsesskey');
-        }
-
-        $strblank = get_string('blank', 'data');
-        $strcontinue = get_string('continue');
-        $strwarning = get_string('mappingwarning', 'data');
-        $strfieldmappings = get_string('fieldmappings', 'data');
-        $strnew = get_string('new');
-
-        $sesskey = sesskey();
-
-        list($settings, $newfields,  $currentfields) = $this->get_settings();
-
-        echo '<div class="presetmapping"><form action="preset.php" method="post">';
-        echo '<div>';
-        echo '<input type="hidden" name="action" value="finishimport" />';
-        echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-        echo '<input type="hidden" name="d" value="'.$this->data->id.'" />';
-        echo '<input type="hidden" name="fullname" value="'.$this->userid.'/'.$this->shortname.'" />';
-
-        if (!empty($currentfields) && !empty($newfields)) {
-            echo "<h3>$strfieldmappings ";
-            echo $OUTPUT->help_icon('fieldmappings', $strfieldmappings, 'data');
-            echo '</h3><table>';
-
-            foreach ($newfields as $nid => $newfield) {
-                echo "<tr><td><label for=\"id_$newfield->name\">$newfield->name</label></td>";
-                echo '<td><select name="field_'.$nid.'" id="id_'.$newfield->name.'">';
-
-                $selected = false;
-                foreach ($currentfields as $cid => $currentfield) {
-                    if ($currentfield->type == $newfield->type) {
-                        if ($currentfield->name == $newfield->name) {
-                            echo '<option value="'.$cid.'" selected="selected">'.$currentfield->name.'</option>';
-                            $selected=true;
-                        }
-                        else {
-                            echo '<option value="'.$cid.'">'.$currentfield->name.'</option>';
-                        }
-                    }
-                }
-
-                if ($selected)
-                    echo '<option value="-1">-</option>';
-                else
-                    echo '<option value="-1" selected="selected">-</option>';
-                echo '</select></td></tr>';
-            }
-            echo '</table>';
-            echo "<p>$strwarning</p>";
-
-        } else if (empty($newfields)) {
-            print_error('nodefinedfields', 'data');
-        }
-
-        echo '<div class="overwritesettings"><label for="overwritesettings">'.get_string('overwritesettings', 'data');
-        echo '<input id="overwritesettings" name="overwritesettings" type="checkbox" /></label></div>';
-
-        echo '<input class="button" type="submit" value="'.$strcontinue.'" /></div></form></div>';
-
-    }
-
-    /**
-     * @global object
-     * @global object
-     * @return bool
-     */
-    function import() {
-        global $CFG, $DB;
-
-        list($settings, $newfields, $currentfields) = $this->get_settings();
-        $preservedfields = array();
-
-        $overwritesettings = optional_param('overwritesettings', 0, PARAM_BOOL);
-
-        /* Maps fields and makes new ones */
-        if (!empty($newfields)) {
-            /* We require an injective mapping, and need to know what to protect */
-            foreach ($newfields as $nid => $newfield) {
-                $cid = optional_param("field_$nid", -1, PARAM_INT);
-                if ($cid == -1) continue;
-
-                if (array_key_exists($cid, $preservedfields)){
-                    print_error('notinjectivemap', 'data');
-                }
-                else $preservedfields[$cid] = true;
-            }
-
-            foreach ($newfields as $nid => $newfield) {
-                $cid = optional_param("field_$nid", -1, PARAM_INT);
-
-                /* A mapping. Just need to change field params. Data kept. */
-                if ($cid != -1 and isset($currentfields[$cid])) {
-                    $fieldobject = data_get_field_from_id($currentfields[$cid]->id, $this->data);
-                    foreach ($newfield as $param => $value) {
-                        if ($param != "id") {
-                            $fieldobject->field->$param = $value;
-                        }
-                    }
-                    unset($fieldobject->field->similarfield);
-                    $fieldobject->update_field();
-                    unset($fieldobject);
-                }
-                /* Make a new field */
-                else {
-                    include_once("field/$newfield->type/field.class.php");
-
-                    if (!isset($newfield->description)) {
-                        $newfield->description = '';
-                    }
-                    $classname = 'data_field_'.$newfield->type;
-                    $fieldclass = new $classname($newfield, $this->data);
-                    $fieldclass->insert_field();
-                    unset($fieldclass);
-                }
-            }
-        }
-
-        /* Get rid of all old unused data */
-        if (!empty($preservedfields)) {
-            foreach ($currentfields as $cid => $currentfield) {
-                if (!array_key_exists($cid, $preservedfields)) {
-                    /* Data not used anymore so wipe! */
-                    print "Deleting field $currentfield->name<br />";
-
-                    $id = $currentfield->id;
-                    //Why delete existing data records and related comments/ratings??
-/*
-                    if ($content = $DB->get_records('data_content', array('fieldid'=>$id))) {
-                        foreach ($content as $item) {
-                            $DB->delete_records('data_ratings', array('recordid'=>$item->recordid));
-                            $DB->delete_records('data_comments', array('recordid'=>$item->recordid));
-                            $DB->delete_records('data_records', array('id'=>$item->recordid));
-                        }
-                    }*/
-                    $DB->delete_records('data_content', array('fieldid'=>$id));
-                    $DB->delete_records('data_fields', array('id'=>$id));
-                }
-            }
-        }
-
-    // handle special settings here
-        if (!empty($settings->defaultsort)) {
-            if (is_numeric($settings->defaultsort)) {
-                // old broken value
-                $settings->defaultsort = 0;
-            } else {
-                $settings->defaultsort = (int)$DB->get_field('data_fields', 'id', array('dataid'=>$this->data->id, 'name'=>$settings->defaultsort));
-            }
-        } else {
-            $settings->defaultsort = 0;
-        }
-
-        // do we want to overwrite all current database settings?
-        if ($overwritesettings) {
-            // all supported settings
-            $overwrite = array_keys((array)$settings);
-        } else {
-            // only templates and sorting
-            $overwrite = array('singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter',
-                               'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate',
-                               'asearchtemplate', 'defaultsortdir', 'defaultsort');
-        }
-
-        // now overwrite current data settings
-        foreach ($this->data as $prop=>$unused) {
-            if (in_array($prop, $overwrite)) {
-                $this->data->$prop = $settings->$prop;
-            }
-        }
-
-        data_update_instance($this->data);
-
-        if (strstr($this->folder, '/temp/')) {
-        // Removes the temporary files
-            clean_preset($this->folder);
-        }
-
-        return true;
-    }
-}
-
-/**
- * @global object
- * @global object
  * @param object $course
  * @param int $userid
  * @param string $shortname
@@ -2912,3 +2546,389 @@
         $datanav->add(get_string('updatethis', '', get_string('modulename', 'choice')), new moodle_url('/course/mod.php', array('update' => $PAGE->cm->id, 'return' => true, 'sesskey' => sesskey())));
     }
 }
+
+/**
+ * This function generates the preset files given a data record
+ *
+ * @param stdClass $file
+ * @param stdClass $data
+ * @return array Array of files
+ */
+function data_prepare_preset_files($file, $data) {
+    global $USER, $DB;
+
+    // Raw settings are not preprocessed during saving of presets
+    $raw_settings = array(
+        'intro',
+        'comments',
+        'requiredentries',
+        'requiredentriestoview',
+        'maxentries',
+        'rssarticles',
+        'approval',
+        'defaultsortdir'
+    );
+
+    // Assemble "preset.xml":
+    $presetxmldata = "<preset>\n\n";
+    $presetxmldata .= "<settings>\n";
+    // First, settings that do not require any conversion
+    foreach ($raw_settings as $setting) {
+        $presetxmldata .= "<$setting>" . htmlspecialchars($data->$setting) . "</$setting>\n";
+    }
+    // Now specific settings
+    if ($data->defaultsort > 0 && $sortfield = data_get_field_from_id($data->defaultsort, $data)) {
+        $presetxmldata .= '<defaultsort>' . htmlspecialchars($sortfield->field->name) . "</defaultsort>\n";
+    } else {
+        $presetxmldata .= "<defaultsort>0</defaultsort>\n";
+    }
+    $presetxmldata .= "</settings>\n\n";
+    // Now for the fields. Grab all that are non-empty
+    if ($fields = $DB->get_records('data_fields', array('dataid'=>$data->id))) {
+        ksort($fields);
+        foreach ($fields as $field) {
+            $presetxmldata .= "<field>\n";
+            foreach ($field as $key => $value) {
+                if ($value != '' && $key != 'id' && $key != 'dataid') {
+                    $presetxmldata .= "<$key>" . htmlspecialchars($value) . "</$key>\n";
+                }
+            }
+            $presetxmldata .= "</field>\n\n";
+        }
+    }
+    $presetxmldata .= '</preset>';
+
+
+    $fs = get_file_storage();
+
+    // An array of all of the files to create and then zip, name=>content
+    $files = array(
+        'preset.xml'=>$presetxmldata,
+        'singletemplate.html'=>$data->singletemplate,
+        'listtemplateheader.xml'=>$data->listtemplateheader,
+        'listtemplate.xml'=>$data->listtemplate,
+        'listtemplatefooter.xml'=>$data->listtemplatefooter,
+        'addtemplate.xml'=>$data->addtemplate,
+        'rsstemplate.xml'=>$data->rsstemplate,
+        'rsstitletemplate.xml'=>$data->rsstitletemplate,
+        'csstemplate.css'=>$data->csstemplate,
+        'jstemplate.js'=>$data->jstemplate,
+        'asearchtemplate.html'=>$data->asearchtemplate,
+    );
+
+    // Create each file in the files array
+    foreach ($files as $filename=>$content) {
+        $currentfile = clone($file);
+        $currentfile->filename = $filename;
+        $files[$filename] = $fs->create_file_from_string($currentfile, $content);
+    }
+
+    return $files;
+}
+
+/**
+ * This function creates a zip file that contains the preset files and sends it to the
+ * user.
+ *
+ * @param stdClass $filedetails
+ * @param array $files
+ */
+function data_send_zip_file($filedetails, array $files) {
+    // Zip all of the files we just created
+    $packer = get_file_packer('application/zip');
+    $file = $packer->archive_to_storage($files, $filedetails->contextid, $filedetails->filearea, $filedetails->itemid, $filedetails->filepath, $filedetails->filename);
+
+    // Deliver the files. We need to ensure that if the user cancels the file still gets deleted
+    // so we must set the final argument to true
+    send_stored_file($file, 0, 0, true, null, true);
+
+    // Remove all of the files... zip included
+    $fs = get_file_storage();
+    $fs->delete_area_files($filedetails->contextid, $filedetails->filearea, $filedetails->itemid);
+}
+
+/**
+ * Abstract class that all preset types should derive from
+ */
+abstract class data_preset {
+    public $course;
+    public $cm;
+    public $data;
+    public $userid;
+    public $shortname;
+    public $type;
+    
+    /**
+     * This function must be overridden and should retrieve the contents for the
+     * requested file from whereever that may exist.
+     * @param string file The filename of the file to get the contents of
+     */
+    abstract protected function get_file_content($file);
+    
+    /**
+     * This method can be used to retrieve the correct type of data preset for a
+     * given preset
+     * @param stdClass $course
+     * @param stdClass $cm
+     * @param stdClass $data
+     * @param stdClass $preset
+     * @return data_preset
+     */
+    final public static function init($course, $cm, $data, stdClass $preset) {
+        switch ($preset->type) {
+            case DATA_PRESET_PREDEFINED:
+                $preset = new data_preset_predefined($course, $cm, $data, $preset);
+                break;
+            case DATA_PRESET_SAVED:
+                $preset = new data_preset_saved($course, $cm, $data, $preset);
+                break;
+            default:
+                throw new coding_exception('Unknown data preset type');
+        }
+        return $preset;
+    }
+    
+    /**
+     * Basic constructor
+     * @param stdClass $course
+     * @param stdClass $cm
+     * @param stdClass $data
+     * @param stdClass $preset
+     */
+    public function __construct($course, $cm, $data, $preset) {
+        $this->course = $course;
+        $this->cm = $cm;
+        $this->data = $data;
+        $this->userid = $preset->userid;
+        $this->shortname = $preset->shortname;
+        $this->type = $preset->type;
+    }
+
+    /**
+     * This function retrieves an the settings and pages for the preset and
+     * returns an array containing the three elements
+     * @return array $settings, $fields, $currentfields
+     */
+    public function get_settings() {
+        global $CFG, $DB;
+
+        /* Grab XML */
+        $parsedxml = xmlize($this->get_file_content('preset.xml'), 0);
+
+        $allowedsettings = array('intro', 'comments', 'requiredentries', 'requiredentriestoview',
+                                  'maxentries', 'rssarticles', 'approval', 'defaultsortdir', 'defaultsort');
+
+        /* First, do settings. Put in user friendly array. */
+        $settingsarray = $parsedxml['preset']['#']['settings'][0]['#'];
+        $settings = new StdClass();
+
+        foreach ($settingsarray as $setting => $value) {
+            if (!is_array($value)) {
+                continue;
+            }
+            if (!in_array($setting, $allowedsettings)) {
+                // unsupported setting
+                continue;
+            }
+            $settings->$setting = $value[0]['#'];
+        }
+
+        /* Now work out fields to user friendly array */
+        $fieldsarray = $parsedxml['preset']['#']['field'];
+        $fields = array();
+        foreach ($fieldsarray as $field) {
+            if (!is_array($field)) {
+                continue;
+            }
+            $f = new StdClass();
+            foreach ($field['#'] as $param => $value) {
+                if (!is_array($value)) {
+                    continue;
+                }
+                $f->$param = $value[0]['#'];
+            }
+            $f->dataid = $this->data->id;
+            $f->type = clean_param($f->type, PARAM_ALPHA);
+            $fields[] = $f;
+        }
+        /* Now add the HTML templates to the settings array so we can update d */
+        $settings->singletemplate     = $this->get_file_content("singletemplate.html");
+        $settings->listtemplate       = $this->get_file_content("listtemplate.html");
+        $settings->listtemplateheader = $this->get_file_content("listtemplateheader.html");
+        $settings->listtemplatefooter = $this->get_file_content("listtemplatefooter.html");
+        $settings->addtemplate        = $this->get_file_content("addtemplate.html");
+        $settings->rsstemplate        = $this->get_file_content("rsstemplate.html");
+        $settings->rsstitletemplate   = $this->get_file_content("rsstitletemplate.html");
+        $settings->csstemplate        = $this->get_file_content("csstemplate.css");
+        $settings->jstemplate         = $this->get_file_content("jstemplate.js");
+        //optional
+        $settings->asearchtemplate    = $this->get_file_content("asearchtemplate.html");
+
+        $settings->instance = $this->data->id;
+
+        /* Now we look at the current structure (if any) to work out whether we need to clear db
+           or save the data */
+        if (!$currentfields = $DB->get_records('data_fields', array('dataid'=>$this->data->id))) {
+            $currentfields = array();
+        }
+
+        return array($settings, $fields, $currentfields);
+    }
+
+    /**
+     * Actually preforms the task of creating the data module within the database
+     * @return bool
+     */
+    public function import() {
+        global $CFG, $DB;
+
+        list($settings, $newfields, $currentfields) = $this->get_settings();
+        $preservedfields = array();
+
+        $overwritesettings = optional_param('overwritesettings', 0, PARAM_BOOL);
+
+        /* Maps fields and makes new ones */
+        if (!empty($newfields)) {
+            /* We require an injective mapping, and need to know what to protect */
+            foreach ($newfields as $nid => $newfield) {
+                $cid = optional_param("field_$nid", -1, PARAM_INT);
+                if ($cid == -1) {
+                    continue;
+                }
+                if (array_key_exists($cid, $preservedfields)){
+                    print_error('notinjectivemap', 'data');
+                }
+                else $preservedfields[$cid] = true;
+            }
+
+            foreach ($newfields as $nid => $newfield) {
+                $cid = optional_param("field_$nid", -1, PARAM_INT);
+
+                /* A mapping. Just need to change field params. Data kept. */
+                if ($cid != -1 and isset($currentfields[$cid])) {
+                    $fieldobject = data_get_field_from_id($currentfields[$cid]->id, $this->data);
+                    foreach ($newfield as $param => $value) {
+                        if ($param != "id") {
+                            $fieldobject->field->$param = $value;
+                        }
+                    }
+                    unset($fieldobject->field->similarfield);
+                    $fieldobject->update_field();
+                    unset($fieldobject);
+                } else {
+                    /* Make a new field */
+                    require_once($CFG->dirroot."/mod/data/field/$newfield->type/field.class.php");
+
+                    if (!isset($newfield->description)) {
+                        $newfield->description = '';
+                    }
+                    $classname = 'data_field_'.$newfield->type;
+                    $fieldclass = new $classname($newfield, $this->data);
+                    $fieldclass->insert_field();
+                    unset($fieldclass);
+                }
+            }
+        }
+
+        /* Get rid of all old unused data */
+        if (!empty($preservedfields)) {
+            foreach ($currentfields as $cid => $currentfield) {
+                if (!array_key_exists($cid, $preservedfields)) {
+                    /* Data not used anymore so wipe! */
+                    print "Deleting field $currentfield->name<br />";
+
+                    $id = $currentfield->id;
+                    //Why delete existing data records and related comments/ratings??
+                    /*
+                    if ($content = $DB->get_records('data_content', array('fieldid'=>$id))) {
+                        foreach ($content as $item) {
+                            $DB->delete_records('data_ratings', array('recordid'=>$item->recordid));
+                            $DB->delete_records('data_comments', array('recordid'=>$item->recordid));
+                            $DB->delete_records('data_records', array('id'=>$item->recordid));
+                        }
+                    }*/
+                    $DB->delete_records('data_content', array('fieldid'=>$id));
+                    $DB->delete_records('data_fields', array('id'=>$id));
+                }
+            }
+        }
+
+    // handle special settings here
+        if (!empty($settings->defaultsort)) {
+            if (is_numeric($settings->defaultsort)) {
+                // old broken value
+                $settings->defaultsort = 0;
+            } else {
+                $settings->defaultsort = (int)$DB->get_field('data_fields', 'id', array('dataid'=>$this->data->id, 'name'=>$settings->defaultsort));
+            }
+        } else {
+            $settings->defaultsort = 0;
+        }
+
+        // do we want to overwrite all current database settings?
+        if ($overwritesettings) {
+            // all supported settings
+            $overwrite = array_keys((array)$settings);
+        } else {
+            // only templates and sorting
+            $overwrite = array('singletemplate', 'listtemplate', 'listtemplateheader', 'listtemplatefooter',
+                               'addtemplate', 'rsstemplate', 'rsstitletemplate', 'csstemplate', 'jstemplate',
+                               'asearchtemplate', 'defaultsortdir', 'defaultsort');
+        }
+
+        // now overwrite current data settings
+        foreach ($this->data as $prop=>$unused) {
+            if (in_array($prop, $overwrite)) {
+                $this->data->$prop = $settings->$prop;
+            }
+        }
+        data_update_instance($this->data);
+        return true;
+    }
+}
+/**
+ * Class used to represent predefined data presets.
+ *
+ * Predefined data presets are presets that exist within the mod/data/preset directory
+ * and are special in that they cannot be delete, or overridden in the system
+ */
+class data_preset_predefined extends data_preset {
+    public $folder;
+    public function __construct($course, $cm, $data, $preset) {
+        parent::__construct($course, $cm, $data, $preset);
+        $this->folder = data_preset_path($course, $this->userid, $this->shortname);
+        if (!is_directory_a_preset($this->folder)) {
+            print_error('invalidpreset', 'data', '', $this->userid.'/'.$this->shortname);
+        }
+    }
+    protected function get_file_content($file) {
+        if (!file_exists($this->folder.'/'.$file)) {
+            return null;
+        }
+        return file_get_contents($this->folder.'/'.$file);
+    }
+}
+/**
+ * Class used for saved data presets
+ *
+ * Saved data presets are presets that people have saved or uploaded and exist
+ * within the file area determined by DATA_PRESET_FILEAREA where the item id
+ * is used to determine the owner of the preset (presets can be used in any data module)
+ * and then exist in a /shortname/ structure.
+ */
+class data_preset_saved extends data_preset {
+    protected $directory;
+    public function  __construct($course, $cm, $data, $preset) {
+        parent::__construct($course, $cm, $data, $preset);
+        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+        $fs = get_file_storage();
+        $this->directory = $fs->get_directory_files($context->id, DATA_PRESET_FILEAREA, $preset->userid, $preset->path);
+    }
+    public function get_file_content($filename) {
+        foreach ($this->directory as $file) {
+            if ($file->get_filename() == $filename) {
+                return $file->get_content();
+            }
+        }
+    }
+}
Index: moodle/mod/data/preset.php
--- moodle/mod/data/preset.php Base (1.50)
+++ moodle/mod/data/preset.php Locally Modified (Based On 1.50)
@@ -29,58 +29,29 @@
  */
 
 require_once('../../config.php');
-require_once('lib.php');
+require_once($CFG->dirroot.'/mod/data/lib.php');
+require_once($CFG->dirroot.'/mod/data/preset_form.php');
 require_once($CFG->libdir.'/uploadlib.php');
 require_once($CFG->libdir.'/xmlize.php');
 
 $id       = optional_param('id', 0, PARAM_INT);    // course module id
 $d        = optional_param('d', 0, PARAM_INT);     // database activity id
-$action   = optional_param('action', 'base', PARAM_ALPHANUM); // current action
-$fullname = optional_param('fullname', '', PARAM_PATH); // directory the preset is in
-$file     = optional_param('file', '', PARAM_PATH); // uploaded file
+$action   = optional_param('action', false, PARAM_ALPHANUM); // current action
 
 $url = new moodle_url('/mod/data/preset.php');
-if ($action !== 'base') {
-    $url->param('action', $action);
-}
-if ($fullname !== '') {
-    $url->param('fullname', $fullname);
-}
-if ($file !== '') {
-    $url->param('file', $file);
-}
 
-// find out preset owner userid and shortname
-$parts = explode('/', $fullname);
-$userid = empty($parts[0]) ? 0 : (int)$parts[0];
-$shortname = empty($parts[1]) ? '' : $parts[1];
-unset($parts);
-unset($fullname);
-
 if ($id) {
     $url->param('id', $id);
     $PAGE->set_url($url);
-    if (! $cm = get_coursemodule_from_id('data', $id)) {
-        print_error('invalidcoursemodule');
-    }
-    if (! $course = $DB->get_record('course', array('id'=>$cm->course))) {
-        print_error('coursemisconf');
-    }
-    if (! $data = $DB->get_record('data', array('id'=>$cm->instance))) {
-        print_error('invalidid', 'data');
-    }
+    $cm = get_coursemodule_from_id('data', $id, 0, false, MUST_EXIST);
+    $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST);
+    $data = $DB->get_record('data', array('id'=>$cm->instance), '*', MUST_EXIST);
 } else if ($d) {
     $url->param('d', $d);
     $PAGE->set_url($url);
-    if (! $data = $DB->get_record('data', array('id'=>$d))) {
-        print_error('invalidid', 'data');
-    }
-    if (! $course = $DB->get_record('course', array('id'=>$data->course))) {
-        print_error('coursemisconf');
-    }
-    if (! $cm = get_coursemodule_from_instance('data', $data->id, $course->id)) {
-        print_error('invalidcoursemodule');
-    }
+    $data = $DB->get_record('data', array('id'=>$d), '*', MUST_EXIST);
+    $course = $DB->get_record('course', array('id'=>$data->course), '*', MUST_EXIST);
+    $cm = get_coursemodule_from_instance('data', $data->id, $course->id, false, MUST_EXIST);
 } else {
     print_error('missingparameter');
 }
@@ -95,455 +66,143 @@
 }
 
 require_login($course->id, false, $cm);
-
 require_capability('mod/data:managetemplates', $context);
 
-if ($userid && ($userid != $USER->id) && !has_capability('mod/data:viewalluserpresets', $context)) {
-    print_error('cannotaccesspresentsother', 'data');
-}
-
-/* Need sesskey security check here for import instruction */
-$sesskey = sesskey();
-
 $PAGE->navbar->add(get_string('presets', 'data'));
 
-/********************************************************************/
-/* Output */
-if ($action !== 'export') {
-    data_print_header($course, $cm, $data, 'presets');
-}
+$renderer = $PAGE->get_renderer('mod_data');
+$allpresets = data_get_available_presets($context);
 
-switch ($action) {
-        /***************** Deleting *****************/
-    case 'confirmdelete' :
-        if (!confirm_sesskey()) { // GET request ok here
-            print_error('invalidsesskey');
-        }
+$properties = array();
+$properties['d'] = $d;
+$properties['context'] = $context;
+$properties['maxbytes'] = $course->maxbytes;
+$properties['presets'] = &$allpresets;
+$properties['userid'] = $USER->id;
+$mform = new data_preset_import_form(null, $properties);
 
-        if ($userid > 0 and ($userid == $USER->id || has_capability('mod/data:manageuserpresets', $context))) {
-           //ok can delete
-        } else {
-            print_error('invalidrequest');
-        }
+$postheadercontent = '';
+if (($formdata = $mform->get_data()) && confirm_sesskey()) {
 
-        $path = data_preset_path($course, $userid, $shortname);
-
-        $strwarning = get_string('deletewarning', 'data').'<br />'.
-                      data_preset_name($shortname, $path);
-
-        $optionsyes = array('fullname' => $userid.'/'.$shortname,
-                         'action' => 'delete',
-                         'd' => $data->id);
-
-        $optionsno = array('d' => $data->id);
-        echo $OUTPUT->confirm($strwarning, new moodle_url('preset.php', $optionsyes), new moodle_url('preset.php', $optionsno));
-        echo $OUTPUT->footer();
+    if (!empty($formdata->exportpreset)) {
+        // This is the zip file that will be created
+        $file = new stdClass;
+        $file->contextid = $context->id;
+        $file->filearea = DATA_PRESET_FILEAREA.'_temp';
+        $file->itemid = $USER->id;
+        $file->filepath = '/';
+        $file->userid = $USER->id;
+        $file->filename = clean_filename($data->name).'-preset-'.gmdate("Ymd_Hi").".zip";
+        $fs = get_file_storage();
+        $fs->delete_area_files($file->contextid, $file->filearea, $file->itemid);
+        $files = data_prepare_preset_files($file, $data);
+        data_send_zip_file($file, $files);
         exit(0);
-        break;
 
-    case 'delete' :
-        if (!data_submitted() and !confirm_sesskey()) {
-            print_error('invalidrequest');
-        }
+    } else if (!empty($formdata->savepreset)) {
 
-        if ($userid > 0 and ($userid == $USER->id || has_capability('mod/data:manageuserpresets', $context))) {
-           //ok can delete
-        } else {
-            print_error('invalidrequest');
-        }
+        $file = new stdClass;
+        $file->contextid = $context->id;
+        $file->filearea = DATA_PRESET_FILEAREA;
+        $file->itemid = $USER->id;
+        $file->filepath = '/'.$formdata->savename.'/';
+        $file->userid = $USER->id;
+        $files = data_prepare_preset_files($file, $data);
+        $mform->add_new_preset($formdata->savename, $USER->id, false);
+        $postheadercontent .= $OUTPUT->notification(get_string('savesuccess', 'data'), 'notifysuccess');
 
-        $presetpath = data_preset_path($course, $userid, $shortname);
+    } else if (!empty($formdata->uploadpreset)) {
 
-        if (!clean_preset($presetpath)) {
-            print_error('cannotdeletepreset', 'data');
+        if (!($file = $mform->save_stored_file('presetzipfile', $context->id, DATA_PRESET_FILEAREA, $USER->id, '/'.$formdata->uploadname.'/'))) {
+            print_error('cannotunzipfile');
         }
-        @rmdir($presetpath);
+        $packer = get_file_packer('application/zip');
+        $file->extract_to_storage(get_file_packer('application/zip'), $context->id, DATA_PRESET_FILEAREA, $USER->id, '/'.$formdata->uploadname.'/', $USER->id);
+        $file->delete();
+        $mform->add_new_preset($formdata->uploadname, $USER->id, true);
+        $postheadercontent .= $OUTPUT->notification(get_string('successpresetuploaded', 'data'), 'notifysuccess');
 
-        $strdeleted = get_string('deleted', 'data');
-        echo $OUTPUT->notification("$shortname $strdeleted", 'notifysuccess');
-        break;
+    } else if (!empty($formdata->importpreset)) {
 
-        /***************** Importing *****************/
-    case 'importpreset' :
-        if (!data_submitted() or !confirm_sesskey()) {
-            print_error('invalidrequest');
-        }
-
-        $pimporter = new PresetImporter($course, $cm, $data, $userid, $shortname);
-        $pimporter->import_options();
-
-        echo $OUTPUT->footer();
-        exit(0);
+        $importer = null;
+        foreach ($allpresets as $preset) {
+            if ($formdata->presetname === $preset->userid.'/'.$preset->shortname) {
+                $importer = data_preset::init($course, $cm, $data, $preset);
         break;
-
-        /* Imports a zip file. */
-    case 'importzip' :
-        if (!data_submitted() or !confirm_sesskey()) {
-            print_error('invalidrequest');
         }
-
-        if (!make_upload_directory('temp/data/'.$USER->id)) {
-            print_error('nopermissiontomkdir');
         }
-
-        $presetfile = $CFG->dataroot.'/temp/data/'.$USER->id;
-        clean_preset($presetfile);
-
-        if (!unzip_file($CFG->dataroot."/$course->id/$file", $presetfile, false)) {
-            print_error('cannotunzipfile');
+        if (!$importer) {
+            print_error('invalidpreset', 'data', '', $formdata->presetname);
         }
-
-        $pimporter = new PresetImporter($course, $cm, $data, -$USER->id, $shortname);
-        $pimporter->import_options();
-
-        echo $OUTPUT->footer();
+        echo $renderer->header($course, $cm, $data, 'presets');
+        echo $renderer->preset_import_options($importer, $data);
+        echo $renderer->footer();
         exit(0);
-        break;
-
-    case 'finishimport':
-        if (!data_submitted() or !confirm_sesskey()) {
-            print_error('invalidrequest');
         }
+}
 
-        $pimporter = new PresetImporter($course, $cm, $data, $userid, $shortname);
-        $pimporter->import();
+/* Output */
+echo $renderer->header($course, $cm, $data, 'presets');
+echo $postheadercontent;
 
-        $strimportsuccess = get_string('importsuccess', 'data');
-        $straddentries = get_string('addentries', 'data');
-        $strtodatabase = get_string('todatabase', 'data');
-        if (!$DB->get_records('data_records', array('dataid'=>$data->id))) {
-            echo $OUTPUT->notification("$strimportsuccess <a href='edit.php?d=$data->id'>$straddentries</a> $strtodatabase", 'notifysuccess');
-        } else {
-            echo $OUTPUT->notification("$strimportsuccess", 'notifysuccess');
+if ($action === 'confirmdelete' || $action === 'delete') {
+    /***************** Deleting *****************/
+    if (!confirm_sesskey()) { // GET request ok here
+        print_error('invalidsesskey');
         }
-        break;
 
-        /* Exports as a zip file ready for download. */
-    case 'export':
-        if (!data_submitted() or !confirm_sesskey()) {
-            print_error('invalidrequest');
+    $presettodel = required_param('preset', PARAM_TEXT);
+    $preset = false;
+    foreach ($allpresets as $temppreset) {
+        if ($temppreset->userid.'/'.$temppreset->shortname === $presettodel) {
+            $preset = $temppreset;
         }
-        $exportfile = data_presets_export($course, $cm, $data);
-        $exportfilename = basename($exportfile);
-        header("Content-Type: application/download\n");
-        header("Content-Disposition: attachment; filename=$exportfilename");
-        header('Expires: 0');
-        header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
-        header('Pragma: public');
-        $exportfilehandler = fopen($exportfile, 'rb');
-        print fread($exportfilehandler, filesize($exportfile));
-        fclose($exportfilehandler);
-        unlink($exportfile);
-        exit(0);
-        break;
+    }
 
-        /***************** Exporting *****************/
-    case 'save1':
-        if (!data_submitted() or !confirm_sesskey()) {
+    if (!$preset || ($preset->userid != $USER->id && !has_capability('mod/data:manageuserpresets', $context))) {
             print_error('invalidrequest');
         }
 
-        $strcontinue = get_string('continue');
-        $strwarning = get_string('presetinfo', 'data');
-        $strname = get_string('shortname');
-
-        echo '<div style="text-align:center">';
-        echo '<p>'.$strwarning.'</p>';
-        echo '<form action="preset.php" method="post">';
-        echo '<fieldset class="invisiblefieldset">';
-        echo '<label for="shorname">'.$strname.'</label> <input type="text" id="shorname" name="name" value="'.$data->name.'" />';
-        echo '<input type="hidden" name="action" value="save2" />';
-        echo '<input type="hidden" name="d" value="'.$data->id.'" />';
-        echo '<input type="hidden" name="sesskey" value="'.$sesskey.'" />';
-        echo '<input type="submit" value="'.$strcontinue.'" /></fieldset></form></div>';
-        echo $OUTPUT->footer();
-        exit(0);
-        break;
-
-    case 'save2':
-        if (!data_submitted() or !confirm_sesskey()) {
-            print_error('invalidrequest');
+    if ($action === 'delete' && data_submitted()) {
+        foreach ($preset->files as $file) {
+            $file->delete();
         }
+        $preset->directory->delete();
 
-        $strcontinue = get_string('continue');
-        $stroverwrite = get_string('overwrite', 'data');
-        $strname = get_string('shortname');
-
-        $name = optional_param('name', $data->name, PARAM_FILE);
-
-        if (is_directory_a_preset("$CFG->dataroot/data/preset/$USER->id/$name")) {
-            echo $OUTPUT->notification("Preset already exists: Pick another name or overwrite");
-
-            echo '<div style="text-align:center">';
-            echo '<form action="preset.php" method="post">';
-            echo '<fieldset class="invisiblefieldset">';
-            echo '<label for="shorname">'.$strname.'</label> <input type="textbox" name="name" value="'.$name.'" />';
-            echo '<input type="hidden" name="action" value="save2" />';
-            echo '<input type="hidden" name="d" value="'.$data->id.'" />';
-            echo '<input type="hidden" name="sesskey" value="'.$sesskey.'" />';
-            echo '<input type="submit" value="'.$strcontinue.'" /></fieldset></form>';
-
-            echo '<form action="preset.php" method="post">';
-            echo '<div>';
-            echo '<input type="hidden" name="name" value="'.$name.'" />';
-            echo '<input type="hidden" name="action" value="save3" />';
-            echo '<input type="hidden" name="d" value="'.$data->id.'" />';
-            echo '<input type="hidden" name="sesskey" value="'.$sesskey.'" />';
-            echo '<input type="submit" value="'.$stroverwrite.'" /></div></form>';
-            echo '</div>';
+        $strdeleted = get_string('deleted', 'data');
+        echo $OUTPUT->notification($preset->shortname." $strdeleted", 'notifysuccess');
+        echo $OUTPUT->continue_button(new moodle_url($CFG->wwwroot.'/mod/data/preset.php', array('d'=>$d)));
+    } else {
+        $optionsyes = array('preset' => $presettodel,'action' => 'delete','d' => $data->id);
+        $optionsno = array('d' => $data->id);
+        echo $OUTPUT->confirm(get_string('deletewarning', 'data'), new moodle_url($CFG->wwwroot.'/mod/data/preset.php', $optionsyes), new moodle_url($CFG->wwwroot.'/mod/data/preset.php', $optionsno));
+    }
             echo $OUTPUT->footer();
             exit(0);
-            break;
-        }
-
-    case 'save3':
+} else if ($action === 'finishimport') {
         if (!data_submitted() or !confirm_sesskey()) {
             print_error('invalidrequest');
         }
+    $presettoimport = required_param('preset', PARAM_TEXT);
 
-        $name = optional_param('name', $data->name, PARAM_FILE);
-        $presetdirectory = "/data/preset/$USER->id/$name";
-
-        make_upload_directory($presetdirectory);
-        clean_preset($CFG->dataroot.$presetdirectory);
-
-        $file = data_presets_export($course, $cm, $data);
-        if (!unzip_file($file, $CFG->dataroot.$presetdirectory, false)) {
-            print_error('cannotunziptopreset', 'data');
-        }
-        echo $OUTPUT->notification(get_string('savesuccess', 'data'), 'notifysuccess');
+    $importer = null;
+    foreach ($allpresets as $preset) {
+        if ($preset->userid.'/'.$preset->shortname == $presettoimport) {
+            $importer = data_preset::init($course, $cm, $data, $preset);
         break;
 }
-
-$presets = data_get_available_presets($context);
-
-$strimport         = get_string('import');
-$strfromfile       = get_string('fromfile', 'data');
-$strchooseorupload = get_string('chooseorupload', 'data');
-$strusestandard    = get_string('usestandard', 'data');
-$strchoose         = get_string('choose');
-$strexport         = get_string('export', 'data');
-$strexportaszip    = get_string('exportaszip', 'data');
-$strsaveaspreset   = get_string('saveaspreset', 'data');
-$strsave           = get_string('save', 'data');
-$strdelete         = get_string('delete');
-
-echo '<div style="text-align:center">';
-echo '<table class="presets" cellpadding="5">';
-echo '<tr><td valign="top" colspan="2" align="center"><h3>'.$strexport.'</h3></td></tr>';
-
-echo '<tr><td><label>'.$strexportaszip.'</label>';
-echo $OUTPUT->help_icon('exportzip', get_string('help'), 'data', false);
-echo '</td><td>';
-$options = array();
-$options['sesskey'] = sesskey();
-$options['action']  = 'export';
-$options['d']       = $data->id;
-echo $OUTPUT->single_button(new moodle_url('preset.php', $options), $strexport);
-echo '</td></tr>';
-
-echo '<tr><td><label>'.$strsaveaspreset.'</label>';
-echo $OUTPUT->help_icon('savepreset', get_string('help'), 'data', false);
-echo '</td><td>';
-$options = array();
-$options['sesskey'] = sesskey();
-$options['action']  = 'save1';
-$options['d']       = $data->id;
-echo $OUTPUT->single_button(new moodle_url('preset.php', $options), $strsave);
-echo '</td></tr>';
-echo '<tr><td valign="top" colspan="2" align="center"><h3>'.$strimport.'</h3></td></tr>';
-echo '<tr><td><label for="fromfile">'.$strfromfile.'</label>';
-echo $OUTPUT->help_icon('importfromfile', get_string('help'), 'data', true);
-echo '</td><td>';
-echo '<form id="uploadpreset" method="post" action="preset.php">';
-echo '<fieldset class="invisiblefieldset">';
-echo '<input type="hidden" name="d" value="'.$data->id.'" />';
-echo '<input type="hidden" name="action" value="importzip" />';
-echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-echo '<input name="file" size="20" value="" id="fromfile" type="text" /><input name="coursefiles" value="'.$strchooseorupload.'" onclick="return openpopup('."'/files/index.php?id={$course->id}&amp;choose=uploadpreset.file', 'coursefiles', 'menubar=0,location=0,scrollbars,resizable,width=750,height=500', 0".');" type="button" />';
-echo '<input type="submit" value="'.$strimport.'" />';
-echo '</fieldset></form>';
-echo '</td></tr>';
-
-echo '<tr valign="top"><td><label>'.$strusestandard.'</label>';
-echo $OUTPUT->help_icon('usepreset', get_string('help'), 'data', true);
-echo '</td><td>';
-
-echo '<form id="presets" method="post" action="preset.php" >';
-echo '<fieldset class="invisiblefieldset">';
-echo '<input type="hidden" name="d" value="'.$data->id.'" />';
-echo '<input type="hidden" name="action" value="importpreset" />';
-echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
-
-$i = 0;
-foreach ($presets as $id => $preset) {
-    $screenshot = '';
-    if (!empty($preset->userid)) {
-        $user = $DB->get_record('user', array('id'=>$preset->userid));
-        $desc = $preset->name.' ('.fullname($user, true).')';
-    } else {
-        $desc = $preset->name;
     }
+    $importer->import();
 
-    if (!empty($preset->screenshot)) {
-        $screenshot = '<img width="150" class="presetscreenshot" src="'.$preset->screenshot.'" alt="'.get_string('screenshot').' '.$desc.'" />&nbsp;';
-    }
-
-    $fullname = $preset->userid.'/'.$preset->shortname;
-
-    $dellink = '';
-    if ($preset->userid > 0 and ($preset->userid == $USER->id || has_capability('mod/data:manageuserpresets', $context))) {
-        $dellink = '&nbsp;<a href="preset.php?d='.$data->id.'&amp;action=confirmdelete&amp;fullname='.$fullname.'&amp;sesskey='.sesskey().'">'.
-                   '<img src="'.$OUTPUT->pix_url('t/delete') . '" class="iconsmall" alt="'.$strdelete.' '.$desc.'" /></a>';
-    }
-
-    echo '<input type="radio" name="fullname" id="usepreset'.$i.'" value="'.$fullname.'" /><label for="usepreset'.$i++.'">'.$desc.'</label>'.$dellink.'<br />';
-}
-echo '<br />';
-echo '<input type="submit" value="'.$strchoose.'" />';
-echo '</fieldset></form>';
-echo '</td></tr>';
-echo '</table>';
-echo '</div>';
-
-echo $OUTPUT->footer();
-exit(0);
-
-################################################################################
-
-
-function data_presets_export($course, $cm, $data) {
-    global $CFG, $DB;
-    $presetname = clean_filename($data->name) . '-preset-' . gmdate("Ymd_Hi");
-    $exportsubdir = "$course->id/moddata/data/$data->id/$presetname";
-    make_upload_directory($exportsubdir);
-    $exportdir = "$CFG->dataroot/$exportsubdir";
-
-    // Assemble "preset.xml":
-    $presetxmldata = "<preset>\n\n";
-
-    // Raw settings are not preprocessed during saving of presets
-    $raw_settings = array(
-        'intro',
-        'comments',
-        'requiredentries',
-        'requiredentriestoview',
-        'maxentries',
-        'rssarticles',
-        'approval',
-        'defaultsortdir'
-    );
-
-    $presetxmldata .= "<settings>\n";
-    // First, settings that do not require any conversion
-    foreach ($raw_settings as $setting) {
-        $presetxmldata .= "<$setting>" . htmlspecialchars($data->$setting) . "</$setting>\n";
-    }
-
-    // Now specific settings
-    if ($data->defaultsort > 0 && $sortfield = data_get_field_from_id($data->defaultsort, $data)) {
-        $presetxmldata .= '<defaultsort>' . htmlspecialchars($sortfield->field->name) . "</defaultsort>\n";
+    $strimportsuccess = get_string('importsuccess', 'data');
+    $straddentries = get_string('addentries', 'data');
+    $strtodatabase = get_string('todatabase', 'data');
+    if (!$DB->get_records('data_records', array('dataid'=>$data->id))) {
+        echo $OUTPUT->notification("$strimportsuccess <a href='edit.php?d=$data->id'>$straddentries</a> $strtodatabase", 'notifysuccess');
     } else {
-        $presetxmldata .= "<defaultsort>0</defaultsort>\n";
+        echo $OUTPUT->notification("$strimportsuccess", 'notifysuccess');
     }
-    $presetxmldata .= "</settings>\n\n";
-
-    // Now for the fields. Grab all that are non-empty
-    $fields = $DB->get_records('data_fields', array('dataid'=>$data->id));
-    ksort($fields);
-    if (!empty($fields)) {
-        foreach ($fields as $field) {
-            $presetxmldata .= "<field>\n";
-            foreach ($field as $key => $value) {
-                if ($value != '' && $key != 'id' && $key != 'dataid') {
-                    $presetxmldata .= "<$key>" . htmlspecialchars($value) . "</$key>\n";
                 }
-            }
-            $presetxmldata .= "</field>\n\n";
-        }
-    }
-    $presetxmldata .= '</preset>';
 
-    // After opening a file in write mode, close it asap
-    $presetxmlfile = fopen($exportdir . '/preset.xml', 'w');
-    fwrite($presetxmlfile, $presetxmldata);
-    fclose($presetxmlfile);
-
-    // Now write the template files
-    $singletemplate = fopen($exportdir . '/singletemplate.html', 'w');
-    fwrite($singletemplate, $data->singletemplate);
-    fclose($singletemplate);
-
-    $listtemplateheader = fopen($exportdir . '/listtemplateheader.html', 'w');
-    fwrite($listtemplateheader, $data->listtemplateheader);
-    fclose($listtemplateheader);
-
-    $listtemplate = fopen($exportdir . '/listtemplate.html', 'w');
-    fwrite($listtemplate, $data->listtemplate);
-    fclose($listtemplate);
-
-    $listtemplatefooter = fopen($exportdir . '/listtemplatefooter.html', 'w');
-    fwrite($listtemplatefooter, $data->listtemplatefooter);
-    fclose($listtemplatefooter);
-
-    $addtemplate = fopen($exportdir . '/addtemplate.html', 'w');
-    fwrite($addtemplate, $data->addtemplate);
-    fclose($addtemplate);
-
-    $rsstemplate = fopen($exportdir . '/rsstemplate.html', 'w');
-    fwrite($rsstemplate, $data->rsstemplate);
-    fclose($rsstemplate);
-
-    $rsstitletemplate = fopen($exportdir . '/rsstitletemplate.html', 'w');
-    fwrite($rsstitletemplate, $data->rsstitletemplate);
-    fclose($rsstitletemplate);
-
-    $csstemplate = fopen($exportdir . '/csstemplate.css', 'w');
-    fwrite($csstemplate, $data->csstemplate);
-    fclose($csstemplate);
-
-    $jstemplate = fopen($exportdir . '/jstemplate.js', 'w');
-    fwrite($jstemplate, $data->jstemplate);
-    fclose($jstemplate);
-
-    $asearchtemplate = fopen($exportdir . '/asearchtemplate.html', 'w');
-    fwrite($asearchtemplate, $data->asearchtemplate);
-    fclose($asearchtemplate);
-
-    // Check if all files have been generated
-    if (! is_directory_a_preset($exportdir)) {
-        print_error('generateerror', 'data');
-    }
-
-    $filelist = array(
-        'preset.xml',
-        'singletemplate.html',
-        'listtemplateheader.html',
-        'listtemplate.html',
-        'listtemplatefooter.html',
-        'addtemplate.html',
-        'rsstemplate.html',
-        'rsstitletemplate.html',
-        'csstemplate.css',
-        'jstemplate.js',
-        'asearchtemplate.html'
-    );
-
-    foreach ($filelist as $key => $file) {
-        $filelist[$key] = $exportdir . '/' . $filelist[$key];
-    }
-
-    $exportfile = "$CFG->dataroot/$course->id/moddata/data/$data->id/$presetname.zip";
-    file_exists($exportfile) && unlink($exportfile);
-    $status = zip_files($filelist, $exportfile);
-    // ToDo: status check
-    foreach ($filelist as $file) {
-        unlink($file);
-    }
-    rmdir($exportdir);
-
-    // Return the full path to the exported preset file:
-    return $exportfile;
-}
-
-
+$mform->display();
+echo $OUTPUT->footer();
Index: moodle/mod/data/preset_form.php
--- moodle/mod/data/preset_form.php No Base Revision
+++ moodle/mod/data/preset_form.php Locally New
@@ -0,0 +1,168 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Moodle renderer used to display special elements of the data module
+ *
+ * @package   mod-data
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ **/
+
+/** We need forms lib */
+require_once($CFG->libdir.'/formslib.php');
+
+$PAGE->requires->yui2_lib('dom');
+$PAGE->requires->yui2_lib('event');
+
+/**
+ * Form used to display the preset import/export options
+ * @package   mod-data
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class data_preset_import_form extends moodleform {
+
+    /**
+     * Standard definition method
+     */
+    public function definition() {
+        global $DB, $OUTPUT, $USER, $CFG;
+        $mform = $this->_form;
+        $d = $this->_customdata['d'];
+        $context = $this->_customdata['context'];
+        $maxbytes = $this->_customdata['maxbytes'];
+        $presets = $this->_customdata['presets'];
+
+        $mform->addElement('hidden', 'd', $d);
+        $mform->setType('d', PARAM_INT);
+
+        $mform->addElement('header', 'export', get_string('export', 'data'));
+        $mform->setHelpButton('export', array('exportzip', get_string('help'), 'data'));
+        $mform->addElement('submit', 'exportpreset', get_string('export', 'data'))->setLabel(get_string('exportaszip', 'data'));
+
+        $mform->addElement('header', 'save', get_string('saveaspreset', 'data'));
+        $mform->setHelpButton('save', array('savepreset', get_string('help'), 'data'));
+        $mform->addElement('text', 'savename', get_string('presetname', 'data'));
+        $mform->addElement('submit', 'savepreset', get_string('save', 'data'));
+
+        $mform->addElement('header', 'uploadanewpreset', get_string('uploadanewpreset', 'data'));
+        $mform->setHelpButton('uploadanewpreset', array('importfromfile', get_string('help'), 'data'));
+        $mform->addElement('text', 'uploadname', get_string('presetname', 'data'));
+        $mform->addElement('filepicker', 'presetzipfile', get_string('fromfile', 'data'), null, array('maxbytes' => $maxbytes, 'filetypes' => array('*.zip')));
+        $mform->addElement('submit', 'uploadpreset', get_string('upload'));
+
+        $mform->addElement('header', 'selectapreset', get_string('usestandard', 'data'));
+        $mform->setHelpButton('selectapreset', array('usepreset', get_string('help'), 'data'));
+        $mform->addElement('hidden', 'presetplaceholder', '0');
+        $canmanage = has_capability('mod/data:manageuserpresets', $context);
+        $strdelete = get_string('delete');
+        $deletelink = new moodle_url($CFG->wwwroot.'/mod/data/preset.php', array('d'=>$d, 'action'=>'confirmdelete', 'sesskey'=>sesskey()));
+        foreach ($presets as $preset) {
+            if (!empty($preset->userid)) {
+                $user = $DB->get_record('user', array('id'=>$preset->userid));
+                $desc = $preset->name.' ('.fullname($user, true).')';
+            } else {
+                $desc = $preset->name;
+            }
+            if ($preset->type !== DATA_PRESET_PREDEFINED && ($preset->userid == $USER->id || $canmanage)) {
+                $link = new html_link(new moodle_url($deletelink, array('preset'=>$preset->userid.'/'.$preset->shortname)));
+                $desc .= '&nbsp;'.$OUTPUT->action_icon($link, $desc, $OUTPUT->pix_url('t/delete'), array('alt'=>$strdelete));
+            }
+            $mform->addElement('radio', 'presetname', null, $desc, $preset->userid.'/'.$preset->shortname);
+        }
+        $mform->addElement('submit', 'importpreset', get_string('choose'));
+    }
+
+    /**
+     * Standard validation method
+     *
+     * @param array $data
+     * @param array $files
+     * @return array empty or with errors ('element'=>'error')
+     */
+    public function validation($data, $files) {
+        $errors = parent::validation($data, $files);
+        if (!empty($data['savepreset'])) {
+            $name = trim($data['savename']);
+            if (empty($name)) {
+                $errors['savename'] = get_string('presetnamerequired', 'data');
+            } else if (!$this->unique_preset_name($name)) {
+                $errors['savename'] = get_string('duplicatepresetname', 'data');
+            }
+        } else if (!empty($data['uploadpreset'])) {
+            $name = trim($data['uploadname']);
+            if (empty($name)) {
+                $errors['uploadname'] = get_string('presetnamerequired', 'data');
+            } else if (!$this->unique_preset_name($name)) {
+                $errors['uploadname'] = get_string('duplicatepresetname', 'data');
+            }
+        }
+        return $errors;
+    }
+
+    /**
+     * Validation check to ensure that a provided name will be a unique preset name
+     * @param string $name
+     * @return bool True for unique false for not
+     */
+    protected function unique_preset_name($name) {
+        $presets = $this->_customdata['presets'];
+        $userid = $this->_customdata['userid'];
+        foreach ($presets as $preset) {
+            if ($preset->shortname == $name && $preset->userid == $userid) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Used to insert a new preset radio element into the form...
+     * This occurs because if the user uploads a zip file containing a preset
+     *
+     * @param string $name
+     * @param int $userid
+     * @param bool $checked
+     * @return stdClass preset object
+     */
+    public function add_new_preset($name, $userid, $checked=true) {
+        global $DB, $OUTPUT, $CFG, $USER;
+        $d = $this->_customdata['d'];
+        $context = $this->_customdata['context'];
+        $canmanage = has_capability('mod/data:manageuserpresets', $context);
+        $deletelink = new moodle_url($CFG->wwwroot.'/mod/data/preset.php', array('d'=>$d, 'action'=>'confirmdelete', 'sesskey'=>sesskey()));
+        $strdelete = get_string('delete');
+        if (!empty($userid)) {
+            $user = $DB->get_record('user', array('id'=>$userid));
+            $desc = $name.' ('.fullname($user, true).')';
+        } else {
+            $desc = $name;
+        }
+        if ($userid == $USER->id || $canmanage) {
+            $link = new html_link(new moodle_url($deletelink, array('preset'=>$userid.'/'.$name)));
+            $desc .= '&nbsp;'.$OUTPUT->action_icon($link, $desc, $OUTPUT->pix_url('t/delete'), array('alt'=>$strdelete));
+        }
+        $preset = new MoodleQuickForm_radio('presetname', null, $desc, $userid.'/'.$name);
+        $outcome = $this->_form->insertElementBefore($preset, 'presetplaceholder')->setChecked($checked);
+        $presetobj = new stdClass;
+        $presetobj->shortname = $name;
+        $presetobj->userid = $userid;
+        $presetobj->type = DATA_PRESET_SAVED;
+        return $presetobj;
+    }
+}
Index: moodle/mod/data/renderer.php
--- moodle/mod/data/renderer.php No Base Revision
+++ moodle/mod/data/renderer.php Locally New
@@ -0,0 +1,137 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file contains the renderers used by the data module
+ *
+ * @package   lesson
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ **/
+
+/**
+ * Moodle renderer used to display core elements of the data module
+ *
+ * @package   lesson
+ * @copyright 2010 Sam Hemelryk
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_data_renderer extends plugin_renderer_base {
+
+    public function header($course, $cm, $data, $currenttab='') {
+        global $CFG, $displaynoticegood, $displaynoticebad;
+        $this->page->set_title($data->name);
+        $this->page->set_heading($course->fullname);
+        $output = '';
+        $output .= $this->output->header();
+        $output .= $this->output->heading(format_string($data->name));
+
+        // Print the tabs
+        if ($currenttab) {
+            // Groups needed for Add entry tab
+            $currentgroup = groups_get_activity_group($cm);
+            $groupmode = groups_get_activity_groupmode($cm);
+            ob_start();
+            include('tabs.php');
+            $output .= ob_get_contents();
+            ob_end_clean();
+        }
+
+        // Print any notices
+        if (!empty($displaynoticegood)) {
+            $output .= $this->output->notification($displaynoticegood, 'notifysuccess');    // good (usually green)
+        } else if (!empty($displaynoticebad)) {
+            $output .= $this->output->notification($displaynoticebad);                     // bad (usuually red)
+        }
+        return $output;
+    }
+
+    public function preset_import_options(data_preset $preset, stdClass $data) {
+        global $CFG;
+
+        list($settings, $newfields,  $currentfields) = $preset->get_settings();
+        if (empty($newfields)) {
+            print_error('nodefinedfields', 'data');
+        }
+
+        $output = '';
+
+        $output .= $this->output_start_tag('div', array('class'=>'presetmapping'));
+        $output .= $this->output_start_tag('form', array('action'=>$CFG->wwwroot.'/mod/data/preset.php', 'method'=>'post'));
+        $output .= $this->output_start_tag('div');
+
+        $output .= $this->output_empty_tag('input', array('type'=>'hidden','name'=>'action', 'value'=>'finishimport'));
+        $output .= $this->output_empty_tag('input', array('type'=>'hidden','name'=>'sesskey', 'value'=>sesskey()));
+        $output .= $this->output_empty_tag('input', array('type'=>'hidden','name'=>'d', 'value'=>$data->id));
+        $output .= $this->output_empty_tag('input', array('type'=>'hidden','name'=>'preset', 'value'=>$preset->userid.'/'.$preset->shortname));
+
+        if (!empty($currentfields)) {
+            $strfieldmappings = get_string('fieldmappings', 'data');
+            $output .= $this->output_tag('h3', null, $strfieldmappings.' '.$this->output->help_icon('fieldmappings', $strfieldmappings, 'data'));
+            $output .= $this->output_start_tag('table');
+
+            foreach ($newfields as $nid => $newfield) {
+                $output .= $this->output_start_tag('tr');
+                $output .= $this->output_start_tag('td');
+                $output .= $this->output_tag('label', array('for'=>'id_'.$newfield->name), $newfield->name);
+                $output .= $this->output_end_tag('td');
+                $output .= $this->output_start_tag('td');
+                $output .= $this->output_start_tag('select', array('name'=>'field_'.$nid, 'id'=>'id_'.$newfield->name));
+
+                $selected = false;
+                foreach ($currentfields as $cid => $currentfield) {
+                    if ($currentfield->type == $newfield->type) {
+                        if ($currentfield->name == $newfield->name) {
+                            $output .= $this->output_tag('option', array('value'=>$cid, 'selected'=>$selected), $currentfield->name);
+                            $selected=true;
+                        } else {
+                            $output .= $this->output_tag('option', array('value'=>$cid), $currentfield->name);
+                        }
+                    }
+                }
+
+                if ($selected) {
+                    $output .= $this->output_tag('option', array('value'=>'-1'), '-');
+                } else {
+                    $output .= $this->output_tag('option', array('value'=>'-1', 'selected'=>$selected), '-');
+                }
+
+                $output .= $this->output_end_tag('select');
+                $output .= $this->output_end_tag('td');
+                $output .= $this->output_end_tag('tr');
+            }
+
+            $output .= $this->output_end_tag('table');
+            $output .= $this->output_tag('p', null, get_string('mappingwarning', 'data'));
+        }
+
+        $output .= $this->output_start_tag('div', array('class'=>'presetmapping'));
+        $output .= $this->output_start_tag('label', array('for'=>'overwritesettings'));
+        $output .= get_string('overwritesettings', 'data');
+        $output .= $this->output_empty_tag('input', array('type'=>'checkbox','id'=>'overwritesettings', 'name'=>'overwritesettings'));
+        $output .= $this->output_end_tag('label');
+        $output .= $this->output_end_tag('div');
+
+        $output .= $this->output_empty_tag('input', array('type'=>'submit','class'=>'button', 'value'=>get_string('continue')));
+        $output .= $this->output_end_tag('div');
+        $output .= $this->output_end_tag('form');
+        $output .= $this->output_end_tag('div');
+        
+        return $output;
+    }
+    
+}
