/** * This function imports an old-school question group file (*.csv,*.sql) * * @param mixed $sFullFilepath Full file patch to the import file * @param mixed $newsid Survey ID to which the question is attached */ function CSVImportGroup($sFullFilepath, $newsid) { global $dbprefix, $connect, $clang; $aLIDReplacements = array(); $aQIDReplacements = array(); // this array will have the "new qid" for the questions, the key will be the "old qid" $aGIDReplacements = array(); $handle = fopen($sFullFilepath, "r"); while (!feof($handle)) { $buffer = fgets($handle); $bigarray[] = $buffer; } fclose($handle); if (substr($bigarray[0], 0, 23) != "# LimeSurvey Group Dump") { $results['fatalerror'] = $clang->gT("This file is not a LimeSurvey question file. Import failed."); $importversion = 0; } else { $importversion = (int) trim(substr($bigarray[1], 12)); } if ((int) $importversion < 112) { $results['fatalerror'] = $clang->gT("This file is too old. Only files from LimeSurvey version 1.50 (DBVersion 112) and newer are supported."); } for ($i = 0; $i < 9; $i++) { unset($bigarray[$i]); } $bigarray = array_values($bigarray); //GROUPS if (array_search("# QUESTIONS TABLE\n", $bigarray)) { $stoppoint = array_search("# QUESTIONS TABLE\n", $bigarray); } elseif (array_search("# QUESTIONS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# QUESTIONS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $grouparray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //QUESTIONS if (array_search("# ANSWERS TABLE\n", $bigarray)) { $stoppoint = array_search("# ANSWERS TABLE\n", $bigarray); } elseif (array_search("# ANSWERS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# ANSWERS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $questionarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //ANSWERS if (array_search("# CONDITIONS TABLE\n", $bigarray)) { $stoppoint = array_search("# CONDITIONS TABLE\n", $bigarray); } elseif (array_search("# CONDITIONS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# CONDITIONS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $answerarray[] = str_replace("`default`", "`default_value`", $bigarray[$i]); } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //CONDITIONS if (array_search("# LABELSETS TABLE\n", $bigarray)) { $stoppoint = array_search("# LABELSETS TABLE\n", $bigarray); } elseif (array_search("# LABELSETS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# LABELSETS TABLE\r\n", $bigarray); } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $conditionsarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //LABELSETS if (array_search("# LABELS TABLE\n", $bigarray)) { $stoppoint = array_search("# LABELS TABLE\n", $bigarray); } elseif (array_search("# LABELS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# LABELS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $labelsetsarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //LABELS if (array_search("# QUESTION_ATTRIBUTES TABLE\n", $bigarray)) { $stoppoint = array_search("# QUESTION_ATTRIBUTES TABLE\n", $bigarray); } elseif (array_search("# QUESTION_ATTRIBUTES TABLE\r\n", $bigarray)) { $stoppoint = array_search("# QUESTION_ATTRIBUTES TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $labelsarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //Question attributes if (!isset($noconditions) || $noconditions != "Y") { // stoppoint is the last line number // this is an empty line after the QA CSV lines $stoppoint = count($bigarray) - 1; for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i <= $stoppoint - 1) { $question_attributesarray[] = $bigarray[$i]; } unset($bigarray[$i]); } } $bigarray = array_values($bigarray); $countgroups = 0; if (isset($questionarray)) { $questionfieldnames = convertCSVRowToArray($questionarray[0], ',', '"'); unset($questionarray[0]); $countquestions = 0; } if (isset($answerarray)) { $answerfieldnames = convertCSVRowToArray($answerarray[0], ',', '"'); unset($answerarray[0]); $countanswers = count($answerarray); } else { $countanswers = 0; } $aLanguagesSupported = array(); // this array will keep all the languages supported for the survey $sBaseLanguage = GetBaseLanguageFromSurveyID($newsid); $aLanguagesSupported[] = $sBaseLanguage; // adds the base language to the list of supported languages $aLanguagesSupported = array_merge($aLanguagesSupported, GetAdditionalLanguagesFromSurveyID($newsid)); // Let's check that imported objects support at least the survey's baselang $langcode = GetBaseLanguageFromSurveyID($newsid); if (isset($grouparray)) { $groupfieldnames = convertCSVRowToArray($grouparray[0], ',', '"'); $langfieldnum = array_search("language", $groupfieldnames); $gidfieldnum = array_search("gid", $groupfieldnames); $groupssupportbaselang = bDoesImportarraySupportsLanguage($grouparray, array($gidfieldnum), $langfieldnum, $sBaseLanguage, true); if (!$groupssupportbaselang) { $results['fatalerror'] = $clang->gT("You can't import a group which doesn't support at least the survey base language."); return $results; } } if (isset($questionarray)) { $langfieldnum = array_search("language", $questionfieldnames); $qidfieldnum = array_search("qid", $questionfieldnames); $questionssupportbaselang = bDoesImportarraySupportsLanguage($questionarray, array($qidfieldnum), $langfieldnum, $sBaseLanguage, true); if (!$questionssupportbaselang) { $results['fatalerror'] = $clang->gT("You can't import a question which doesn't support at least the survey base language."); return $results; } } if ($countanswers > 0) { $langfieldnum = array_search("language", $answerfieldnames); $answercodefilednum1 = array_search("qid", $answerfieldnames); $answercodefilednum2 = array_search("code", $answerfieldnames); $answercodekeysarr = array($answercodefilednum1, $answercodefilednum2); $answerssupportbaselang = bDoesImportarraySupportsLanguage($answerarray, $answercodekeysarr, $langfieldnum, $sBaseLanguage); if (!$answerssupportbaselang) { $results['fatalerror'] = $clang->gT("You can't import answers which doesn't support at least the survey base language."); return $results; } } if (count($labelsetsarray) > 1) { $labelsetfieldname = convertCSVRowToArray($labelsetsarray[0], ',', '"'); $langfieldnum = array_search("languages", $labelsetfieldname); $lidfilednum = array_search("lid", $labelsetfieldname); $labelsetssupportbaselang = bDoesImportarraySupportsLanguage($labelsetsarray, array($lidfilednum), $langfieldnum, $sBaseLanguage, true); if (!$labelsetssupportbaselang) { $results['fatalerror'] = $clang->gT("You can't import label sets which don't support the current survey's base language"); return $results; } } // I assume that if a labelset supports the survey's baselang, // then it's labels do support it as well //DO ANY LABELSETS FIRST, SO WE CAN KNOW WHAT THEIR NEW LID IS FOR THE QUESTIONS $results['labelsets'] = 0; $qtypes = getqtypelist("", "array"); $results['labels'] = 0; $results['labelsets'] = 0; $results['answers'] = 0; $results['subquestions'] = 0; //Do label sets if (isset($labelsetsarray) && $labelsetsarray) { $csarray = buildLabelSetCheckSumArray(); // build checksums over all existing labelsets $count = 0; foreach ($labelsetsarray as $lsa) { $fieldorders = convertCSVRowToArray($labelsetsarray[0], ',', '"'); $fieldcontents = convertCSVRowToArray($lsa, ',', '"'); if ($count == 0) { $count++; continue; } $labelsetrowdata = array_combine($fieldorders, $fieldcontents); // Save old labelid $oldlid = $labelsetrowdata['lid']; unset($labelsetrowdata['lid']); $newvalues = array_values($labelsetrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $lsainsert = "INSERT INTO {$dbprefix}labelsets (" . implode(',', array_keys($labelsetrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; //handle db prefix $lsiresult = $connect->Execute($lsainsert); $results['labelsets']++; // Get the new insert id for the labels inside this labelset $newlid = $connect->Insert_ID("{$dbprefix}labelsets", 'lid'); if ($labelsarray) { $count = 0; foreach ($labelsarray as $la) { $lfieldorders = convertCSVRowToArray($labelsarray[0], ',', '"'); $lfieldcontents = convertCSVRowToArray($la, ',', '"'); if ($count == 0) { $count++; continue; } // Combine into one array with keys and values since its easier to handle $labelrowdata = array_combine($lfieldorders, $lfieldcontents); $labellid = $labelrowdata['lid']; if ($importversion <= 132) { $labelrowdata["assessment_value"] = (int) $labelrowdata["code"]; } if ($labellid == $oldlid) { $labelrowdata['lid'] = $newlid; // translate internal links $labelrowdata['title'] = translink('label', $oldlid, $newlid, $labelrowdata['title']); $newvalues = array_values($labelrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $lainsert = "INSERT INTO {$dbprefix}labels (" . implode(',', array_keys($labelrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; //handle db prefix $liresult = $connect->Execute($lainsert); if ($liresult !== false) { $results['labels']++; } } } } //CHECK FOR DUPLICATE LABELSETS $thisset = ""; $query2 = "SELECT code, title, sortorder, language, assessment_value\n FROM {$dbprefix}labels\n WHERE lid=" . $newlid . "\n ORDER BY language, sortorder, code"; $result2 = db_execute_num($query2) or safe_die("Died querying labelset {$lid}<br />{$query2}<br />" . $connect->ErrorMsg()); while ($row2 = $result2->FetchRow()) { $thisset .= implode('.', $row2); } // while $newcs = dechex(crc32($thisset) * 1); unset($lsmatch); if (isset($csarray)) { foreach ($csarray as $key => $val) { if ($val == $newcs) { $lsmatch = $key; } } } if (isset($lsmatch) || $_SESSION['USER_RIGHT_MANAGE_LABEL'] != 1) { //There is a matching labelset or the user is not allowed to edit labels - // So, we will delete this one and refer to the matched one. $query = "DELETE FROM {$dbprefix}labels WHERE lid={$newlid}"; $result = $connect->Execute($query) or safe_die("Couldn't delete labels<br />{$query}<br />" . $connect->ErrorMsg()); $results['labels'] = $results['labels'] - $connect->Affected_Rows(); $query = "DELETE FROM {$dbprefix}labelsets WHERE lid={$newlid}"; $result = $connect->Execute($query) or safe_die("Couldn't delete labelset<br />{$query}<br />" . $connect->ErrorMsg()); $results['labelsets'] = $results['labelsets'] - $connect->Affected_Rows(); $newlid = $lsmatch; } else { //There isn't a matching labelset, add this checksum to the $csarray array $csarray[$newlid] = $newcs; } //END CHECK FOR DUPLICATES $aLIDReplacements[$oldlid] = $newlid; } } // Import groups if (isset($grouparray) && $grouparray) { // do GROUPS $gafieldorders = convertCSVRowToArray($grouparray[0], ',', '"'); unset($grouparray[0]); $newgid = 0; $group_order = 0; // just to initialize this variable foreach ($grouparray as $ga) { $gacfieldcontents = convertCSVRowToArray($ga, ',', '"'); $grouprowdata = array_combine($gafieldorders, $gacfieldcontents); // Skip not supported languages if (!in_array($grouprowdata['language'], $aLanguagesSupported)) { $skippedlanguages[] = $grouprowdata['language']; // this is for the message in the end. continue; } // replace the sid $oldsid = $grouprowdata['sid']; $grouprowdata['sid'] = $newsid; // replace the gid or remove it if needed (it also will calculate the group order if is a new group) $oldgid = $grouprowdata['gid']; if ($newgid == 0) { unset($grouprowdata['gid']); // find the maximum group order and use this grouporder+1 to assign it to the new group $qmaxgo = "select max(group_order) as maxgo from " . db_table_name('groups') . " where sid={$newsid}"; $gres = db_execute_assoc($qmaxgo) or safe_die($clang->gT("Error") . " Failed to find out maximum group order value<br />\n{$qmaxqo}<br />\n" . $connect->ErrorMsg()); $grow = $gres->FetchRow(); $group_order = $grow['maxgo'] + 1; } else { $grouprowdata['gid'] = $newgid; } $grouprowdata["group_order"] = $group_order; // Everything set - now insert it $grouprowdata = array_map('convertCsvreturn2return', $grouprowdata); // translate internal links $grouprowdata['group_name'] = translink('survey', $oldsid, $newsid, $grouprowdata['group_name']); $grouprowdata['description'] = translink('survey', $oldsid, $newsid, $grouprowdata['description']); db_switchIDInsert('groups', true); $tablename = $dbprefix . 'groups'; $ginsert = $connect->GetinsertSQL($tablename, $grouprowdata); $gres = $connect->Execute($ginsert) or safe_die($clang->gT('Error') . ": Failed to insert group<br />\n{$ginsert}<br />\n" . $connect->ErrorMsg()); db_switchIDInsert('groups', false); //GET NEW GID .... if is not done before and we count a group if a new gid is required if ($newgid == 0) { $newgid = $connect->Insert_ID("{$dbprefix}groups", 'gid'); $countgroups++; } } // GROUPS is DONE // Import questions if (isset($questionarray) && $questionarray) { foreach ($questionarray as $qa) { $qacfieldcontents = convertCSVRowToArray($qa, ',', '"'); $questionrowdata = array_combine($questionfieldnames, $qacfieldcontents); $questionrowdata = array_map('convertCsvreturn2return', $questionrowdata); $questionrowdata["type"] = strtoupper($questionrowdata["type"]); // Skip not supported languages if (!in_array($questionrowdata['language'], $aLanguagesSupported)) { continue; } // replace the sid $questionrowdata["sid"] = $newsid; // replace the gid (if the gid is not in the oldgid it means there is a problem with the exported record, so skip it) if ($questionrowdata['gid'] == $oldgid) { $questionrowdata['gid'] = $newgid; } else { continue; } // a problem with this question record -> don't consider if (isset($aQIDReplacements[$questionrowdata['qid']])) { $questionrowdata['qid'] = $aQIDReplacements[$questionrowdata['qid']]; } else { $oldqid = $questionrowdata['qid']; unset($questionrowdata['qid']); } // Save the following values - will need them for proper conversion later if ((int)$questionrowdata['lid']>0) unset($oldlid1); unset($oldlid2); if (isset($questionrowdata['lid']) && $questionrowdata['lid'] > 0) { $oldlid1 = $questionrowdata['lid']; } if (isset($questionrowdata['lid1']) && $questionrowdata['lid1'] > 0) { $oldlid2 = $questionrowdata['lid1']; } unset($questionrowdata['lid']); unset($questionrowdata['lid1']); if ($questionrowdata['type'] == 'W') { $questionrowdata['type'] = '!'; } elseif ($questionrowdata['type'] == 'Z') { $questionrowdata['type'] = 'L'; } if (!isset($questionrowdata["question_order"]) || $questionrowdata["question_order"] == '') { $questionrowdata["question_order"] = 0; } $questionrowdata = array_map('convertCsvreturn2return', $questionrowdata); // translate internal links $questionrowdata['title'] = translink('survey', $oldsid, $newsid, $questionrowdata['title']); $questionrowdata['question'] = translink('survey', $oldsid, $newsid, $questionrowdata['question']); $questionrowdata['help'] = translink('survey', $oldsid, $newsid, $questionrowdata['help']); $newvalues = array_values($questionrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly if (isset($questionrowdata['qid'])) { db_switchIDInsert('questions', true); } $tablename = $dbprefix . 'questions'; $qinsert = $connect->GetInsertSQL($tablename, $questionrowdata); $qres = $connect->Execute($qinsert) or safe_die($clang->gT("Error") . ": Failed to insert question<br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); $results['questions']++; //GET NEW QID .... if is not done before and we count a question if a new qid is required if (isset($questionrowdata['qid'])) { $saveqid = $questionrowdata['qid']; } else { $aQIDReplacements[$oldqid] = $connect->Insert_ID("{$dbprefix}questions", 'qid'); $saveqid = $aQIDReplacements[$oldqid]; } $qtypes = getqtypelist("", "array"); $aSQIDReplacements = array(); db_switchIDInsert('questions', false); // Now we will fix up old label sets where they are used as answers if ((isset($oldlid1) || isset($oldlid2)) && ($qtypes[$questionrowdata['type']]['answerscales'] > 0 || $qtypes[$questionrowdata['type']]['subquestions'] > 1)) { $query = "select * from " . db_table_name('labels') . " where lid={$aLIDReplacements[$oldlid1]} and language='{$questionrowdata['language']}'"; $oldlabelsresult = db_execute_assoc($query); while ($labelrow = $oldlabelsresult->FetchRow()) { if (in_array($labelrow['language'], $aLanguagesSupported)) { if ($qtypes[$questionrowdata['type']]['subquestions'] < 2) { $qinsert = "insert INTO " . db_table_name('answers') . " (qid,code,answer,sortorder,language,assessment_value)\n VALUES ({$aQIDReplacements[$oldqid]}," . db_quoteall($labelrow['code']) . "," . db_quoteall($labelrow['title']) . "," . db_quoteall($labelrow['sortorder']) . "," . db_quoteall($labelrow['language']) . "," . db_quoteall($labelrow['assessment_value']) . ")"; $qres = $connect->Execute($qinsert) or safe_die($clang->gT("Error") . ": Failed to insert answer (lid1) <br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); } else { if (isset($aSQIDReplacements[$labelrow['code'] . '_' . $saveqid])) { $fieldname = 'qid,'; $data = $aSQIDReplacements[$labelrow['code'] . '_' . $saveqid] . ','; } else { $fieldname = ''; $data = ''; } $qinsert = "insert INTO " . db_table_name('questions') . " ({$fieldname} parent_qid,title,question,question_order,language,scale_id,type, sid, gid)\n VALUES ({$data}{$aQIDReplacements[$oldqid]}," . db_quoteall($labelrow['code']) . "," . db_quoteall($labelrow['title']) . "," . db_quoteall($labelrow['sortorder']) . "," . db_quoteall($labelrow['language']) . ",1,'{$questionrowdata['type']}',{$questionrowdata['sid']},{$questionrowdata['gid']})"; $qres = $connect->Execute($qinsert) or safe_die($clang->gT("Error") . ": Failed to insert question <br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); if ($fieldname == '') { $aSQIDReplacements[$labelrow['code'] . '_' . $saveqid] = $connect->Insert_ID("{$dbprefix}questions", "qid"); } } } } if (isset($oldlid2) && $qtypes[$questionrowdata['type']]['answerscales'] > 1) { $query = "select * from " . db_table_name('labels') . " where lid={$aLIDReplacements[$oldlid2]} and language='{$questionrowdata['language']}'"; $oldlabelsresult = db_execute_assoc($query); while ($labelrow = $oldlabelsresult->FetchRow()) { $qinsert = "insert INTO " . db_table_name('answers') . " (qid,code,answer,sortorder,language,assessment_value,scale_id)\n VALUES ({$aQIDReplacements[$oldqid]}," . db_quoteall($labelrow['code']) . "," . db_quoteall($labelrow['title']) . "," . db_quoteall($labelrow['sortorder']) . "," . db_quoteall($labelrow['language']) . "," . db_quoteall($labelrow['assessment_value']) . ",1)"; $qres = $connect->Execute($qinsert) or safe_die($clang->gT("Error") . ": Failed to insert answer (lid2)<br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); } } } } } //Do answers $results['subquestions'] = 0; if (isset($answerarray) && $answerarray) { foreach ($answerarray as $aa) { $answerfieldcontents = convertCSVRowToArray($aa, ',', '"'); $answerrowdata = array_combine($answerfieldnames, $answerfieldcontents); if ($answerrowdata === false) { $importquestion .= '<br />' . $clang->gT("Faulty line in import - fields and data don't match") . ":" . implode(',', $answerfieldcontents); } // Skip not supported languages if (!in_array($answerrowdata['language'], $aLanguagesSupported)) { continue; } // replace the qid for the new one (if there is no new qid in the $aQIDReplacements array it mean that this answer is orphan -> error, skip this record) if (isset($aQIDReplacements[$answerrowdata["qid"]])) { $answerrowdata["qid"] = $aQIDReplacements[$answerrowdata["qid"]]; } else { continue; } // a problem with this answer record -> don't consider if ($importversion <= 132) { $answerrowdata["assessment_value"] = (int) $answerrowdata["code"]; } // Convert default values for single select questions $questiontemp = $connect->GetRow('select type,gid from ' . db_table_name('questions') . ' where qid=' . $answerrowdata["qid"]); $oldquestion['newtype'] = $questiontemp['type']; $oldquestion['gid'] = $questiontemp['gid']; if ($answerrowdata['default_value'] == 'Y' && ($oldquestion['newtype'] == 'L' || $oldquestion['newtype'] == 'O' || $oldquestion['newtype'] == '!')) { $insertdata = array(); $insertdata['qid'] = $newqid; $insertdata['language'] = $answerrowdata['language']; $insertdata['defaultvalue'] = $answerrowdata['answer']; $query = $connect->GetInsertSQL($dbprefix . 'defaultvalues', $insertdata); $qres = $connect->Execute($query) or safe_die("Error: Failed to insert defaultvalue <br />{$query}<br />\n" . $connect->ErrorMsg()); } // translate internal links $answerrowdata['answer'] = translink('survey', $oldsid, $newsid, $answerrowdata['answer']); // Everything set - now insert it $answerrowdata = array_map('convertCsvreturn2return', $answerrowdata); if ($qtypes[$oldquestion['newtype']]['subquestions'] > 0) { $questionrowdata = array(); if (isset($aSQIDReplacements[$answerrowdata['code'] . $answerrowdata['qid']])) { $questionrowdata['qid'] = $aSQIDReplacements[$answerrowdata['code'] . $answerrowdata['qid']]; } $questionrowdata['parent_qid'] = $answerrowdata['qid']; $questionrowdata['sid'] = $newsid; $questionrowdata['gid'] = $oldquestion['gid']; $questionrowdata['title'] = $answerrowdata['code']; $questionrowdata['question'] = $answerrowdata['answer']; $questionrowdata['question_order'] = $answerrowdata['sortorder']; $questionrowdata['language'] = $answerrowdata['language']; $questionrowdata['type'] = $oldquestion['newtype']; $tablename = $dbprefix . 'questions'; $query = $connect->GetInsertSQL($tablename, $questionrowdata); if (isset($questionrowdata['qid'])) { db_switchIDInsert('questions', true); } $qres = $connect->Execute($query) or safe_die("Error: Failed to insert subquestion <br />{$query}<br />" . $connect->ErrorMsg()); if (!isset($questionrowdata['qid'])) { $aSQIDReplacements[$answerrowdata['code'] . $answerrowdata['qid']] = $connect->Insert_ID("{$dbprefix}questions", "qid"); } else { db_switchIDInsert('questions', false); } $results['subquestions']++; // also convert default values subquestions for multiple choice if ($answerrowdata['default_value'] == 'Y' && ($oldquestion['newtype'] == 'M' || $oldquestion['newtype'] == 'P')) { $insertdata = array(); $insertdata['qid'] = $newqid; $insertdata['sqid'] = $aSQIDReplacements[$answerrowdata['code']]; $insertdata['language'] = $answerrowdata['language']; $insertdata['defaultvalue'] = 'Y'; $tablename = $dbprefix . 'defaultvalues'; $query = $connect->GetInsertSQL($tablename, $insertdata); $qres = $connect->Execute($query) or safe_die("Error: Failed to insert defaultvalue <br />{$query}<br />\n" . $connect->ErrorMsg()); } } else { unset($answerrowdata['default_value']); $tablename = $dbprefix . 'answers'; $query = $connect->GetInsertSQL($tablename, $answerrowdata); $ares = $connect->Execute($query) or safe_die("Error: Failed to insert answer<br />{$query}<br />\n" . $connect->ErrorMsg()); $results['answers']++; } } } // ANSWERS is DONE // Fix sortorder of the groups - if users removed groups manually from the csv file there would be gaps fixSortOrderGroups($surveyid); //... and for the questions inside the groups // get all group ids and fix questions inside each group $gquery = "SELECT gid FROM {$dbprefix}groups where sid={$newsid} group by gid ORDER BY gid"; //Get last question added (finds new qid) $gres = db_execute_assoc($gquery); while ($grow = $gres->FetchRow()) { fixsortorderQuestions($grow['gid'], $newsid); } } $results['question_attributes'] = 0; // Finally the question attributes - it is called just once and only if there was a question if (isset($question_attributesarray) && $question_attributesarray) { //ONLY DO THIS IF THERE ARE QUESTION_ATTRIBUES $fieldorders = convertCSVRowToArray($question_attributesarray[0], ',', '"'); unset($question_attributesarray[0]); foreach ($question_attributesarray as $qar) { $fieldcontents = convertCSVRowToArray($qar, ',', '"'); $qarowdata = array_combine($fieldorders, $fieldcontents); // replace the qid for the new one (if there is no new qid in the $aQIDReplacements array it mean that this attribute is orphan -> error, skip this record) if (isset($aQIDReplacements[$qarowdata["qid"]])) { $qarowdata["qid"] = $aQIDReplacements[$qarowdata["qid"]]; } else { continue; } // a problem with this answer record -> don't consider unset($qarowdata["qaid"]); $tablename = "{$dbprefix}question_attributes"; $qainsert = $connect->GetInsertSQL($tablename, $qarowdata); $result = $connect->Execute($qainsert); if ($result !== false) { $results['question_attributes']++; } } } // ATTRIBUTES is DONE // do CONDITIONS $results['conditions'] = 0; if (isset($conditionsarray) && $conditionsarray) { $fieldorders = convertCSVRowToArray($conditionsarray[0], ',', '"'); unset($conditionsarray[0]); foreach ($conditionsarray as $car) { $fieldcontents = convertCSVRowToArray($car, ',', '"'); $conditionrowdata = array_combine($fieldorders, $fieldcontents); $oldqid = $conditionrowdata["qid"]; $oldcqid = $conditionrowdata["cqid"]; // replace the qid for the new one (if there is no new qid in the $aQIDReplacements array it mean that this condition is orphan -> error, skip this record) if (isset($aQIDReplacements[$oldqid])) { $conditionrowdata["qid"] = $aQIDReplacements[$oldqid]; } else { continue; } // a problem with this answer record -> don't consider // replace the cqid for the new one (if there is no new qid in the $aQIDReplacements array it mean that this condition is orphan -> error, skip this record) if (isset($aQIDReplacements[$oldcqid])) { $conditionrowdata["cqid"] = $aQIDReplacements[$oldcqid]; } else { continue; } // a problem with this answer record -> don't consider list($oldcsid, $oldcgid, $oldqidanscode) = explode("X", $conditionrowdata["cfieldname"], 3); if ($oldcgid != $oldgid) { // this means that the condition is in another group (so it should not have to be been exported -> skip it continue; } unset($conditionrowdata["cid"]); // recreate the cfieldname with the new IDs if (preg_match("/^\\+/", $oldcsid)) { $newcfieldname = '+' . $newsid . "X" . $newgid . "X" . $conditionrowdata["cqid"] . substr($oldqidanscode, strlen($oldqid)); } else { $newcfieldname = $newsid . "X" . $newgid . "X" . $conditionrowdata["cqid"] . substr($oldqidanscode, strlen($oldqid)); } $conditionrowdata["cfieldname"] = $newcfieldname; if (!isset($conditionrowdata["method"]) || trim($conditionrowdata["method"]) == '') { $conditionrowdata["method"] = '=='; } $newvalues = array_values($conditionrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $conditioninsert = "insert INTO {$dbprefix}conditions (" . implode(',', array_keys($conditionrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; $result = $connect->Execute($conditioninsert) or safe_die("Couldn't insert condition<br />{$conditioninsert}<br />" . $connect->ErrorMsg()); $results['conditions']++; } } LimeExpressionManager::RevertUpgradeConditionsToRelevance($newsid); LimeExpressionManager::UpgradeConditionsToRelevance($newsid); $results['groups'] = 1; $results['newgid'] = $newgid; return $results; }
/** * * Enter description here... * @param $surveyid * @param $sMod * @param $newGroup * @return unknown_type */ function importQuestion($surveyid, $sMod, $newGroup = false) { global $connect; global $dbprefix; $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; include "lsrc.config.php"; $newsid = $surveyid; $this->debugLsrc("wir sind in " . __FUNCTION__ . " Line " . __LINE__ . ", START OK {$dbprefix} "); //$getGidSql = "SELECT gid FROM {$dbprefix} "; $getGidSql = "SELECT gid\r\n\t FROM {$dbprefix}groups \r\n\t WHERE sid=" . $surveyid . " AND language='" . GetBaseLanguageFromSurveyID($surveyid) . "'\r\n\t ORDER BY gid desc "; $getGidRs = db_execute_num($getGidSql); $gidRow = $getGidRs->FetchRow(); $gid = $gidRow[0]; if ($gid == '') { $this->debugLsrc("No Group for importing the question, available!"); return "No Group for importing the question, available! Import failed."; } if ($newGroup === true) { ++$gid; } $the_full_file_path = $queDir . $sMod . ".csv"; $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK {$the_full_file_path} "); $handle = fopen($the_full_file_path, "r"); while (!feof($handle)) { $buffer = fgets($handle, 10240); //To allow for very long survey welcomes (up to 10k) $bigarray[] = $buffer; } fclose($handle); // Now we try to determine the dataformat of the survey file. if (substr($bigarray[1], 0, 24) == "# SURVEYOR QUESTION DUMP" && substr($bigarray[4], 0, 29) == "# http://www.phpsurveyor.org/") { $importversion = 100; // version 1.0 file } elseif (substr($bigarray[1], 0, 24) == "# SURVEYOR QUESTION DUMP" && substr($bigarray[4], 0, 37) == "# http://phpsurveyor.sourceforge.net/") { $importversion = 99; // Version 0.99 file or older - carries a different URL } elseif (substr($bigarray[0], 0, 26) == "# LimeSurvey Question Dump" || substr($bigarray[0], 0, 27) == "# PHPSurveyor Question Dump") { // Wow.. this seems to be a >1.0 version file - these files carry the version information to read in line two $importversion = substr($bigarray[1], 12, 3); } else { // $importquestion .= "<strong><font color='red'>".("Error")."</font></strong>\n"; // $importquestion .= ("This file is not a LimeSurvey question file. Import failed.")."\n"; // $importquestion .= "</font></td></tr></table>\n"; // $importquestion .= "</body>\n</html>\n"; // unlink($the_full_file_path); return "This is not a Limesurvey question file. Import failed"; } // if ($importversion != $dbversionnumber) // { //// $importquestion .= "<strong><font color='red'>".("Error")."</font></strong>\n"; //// $importquestion .= ("Sorry, importing questions is limited to the same version. Import failed.")."\n"; //// $importquestion .= "</font></td></tr></table>\n"; //// $importquestion .= "</body>\n</html>\n"; //// unlink($the_full_file_path); // return; // } $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); for ($i = 0; $i < 9; $i++) { unset($bigarray[$i]); } $bigarray = array_values($bigarray); $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); //QUESTIONS if (array_search("# ANSWERS TABLE\n", $bigarray)) { $stoppoint = array_search("# ANSWERS TABLE\n", $bigarray); } elseif (array_search("# ANSWERS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# ANSWERS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $questionarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); //ANSWERS if (array_search("# LABELSETS TABLE\n", $bigarray)) { $stoppoint = array_search("# LABELSETS TABLE\n", $bigarray); } elseif (array_search("# LABELSETS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# LABELSETS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $answerarray[] = str_replace("`default`", "`default_value`", $bigarray[$i]); } unset($bigarray[$i]); } $bigarray = array_values($bigarray); $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); //LABELSETS if (array_search("# LABELS TABLE\n", $bigarray)) { $stoppoint = array_search("# LABELS TABLE\n", $bigarray); } elseif (array_search("# LABELS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# LABELS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $labelsetsarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); //LABELS if (array_search("# QUESTION_ATTRIBUTES TABLE\n", $bigarray)) { $stoppoint = array_search("# QUESTION_ATTRIBUTES TABLE\n", $bigarray); } elseif (array_search("# QUESTION_ATTRIBUTES TABLE\r\n", $bigarray)) { $stoppoint = array_search("# QUESTION_ATTRIBUTES TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $labelsarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); //Question_attributes if (!isset($noconditions) || $noconditions != "Y") { $stoppoint = count($bigarray); for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 1) { $question_attributesarray[] = $bigarray[$i]; } unset($bigarray[$i]); } } $bigarray = array_values($bigarray); if (isset($questionarray)) { $countquestions = count($questionarray) - 1; } else { $countquestions = 0; } if (isset($answerarray)) { $answerfieldnames = convertCSVRowToArray($answerarray[0], ',', '"'); unset($answerarray[0]); $countanswers = count($answerarray); } else { $countanswers = 0; } if (isset($labelsetsarray)) { $countlabelsets = count($labelsetsarray) - 1; } else { $countlabelsets = 0; } if (isset($labelsarray)) { $countlabels = count($labelsarray) - 1; } else { $countlabels = 0; } if (isset($question_attributesarray)) { $countquestion_attributes = count($question_attributesarray) - 1; } else { $countquestion_attributes = 0; } $languagesSupported = array(); // this array will keep all the languages supported for the survey // Let's check that imported objects support at least the survey's baselang $langcode = GetBaseLanguageFromSurveyID($surveyid); $languagesSupported[$langcode] = 1; // adds the base language to the list of supported languages $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); if ($countquestions > 0) { $questionfieldnames = convertCSVRowToArray($questionarray[0], ',', '"'); $langfieldnum = array_search("language", $questionfieldnames); $qidfieldnum = array_search("qid", $questionfieldnames); $questionssupportbaselang = bDoesImportarraySupportsLanguage($questionarray, array($qidfieldnum), $langfieldnum, $langcode, true); if (!$questionssupportbaselang) { // $importquestion .= "<strong><font color='red'>".("Error")."</font></strong>\n" // .("You can't import a question which doesn't support the current survey's base language")."\n" // ."</td></tr></table>\n"; // unlink($the_full_file_path); return "You can't import a question which doesn't support the current survey's base language"; } } $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); foreach (GetAdditionalLanguagesFromSurveyID($surveyid) as $language) { $languagesSupported[$language] = 1; } // Let's assume that if the questions do support tye baselang // Then the answers do support it as well. // ==> So the following section is commented for now //if ($countanswers > 0) //{ // $langfieldnum = array_search("language", $answerfieldnames); // $answercodefilednum1 = array_search("qid", $answerfieldnames); // $answercodefilednum2 = array_search("code", $answerfieldnames); // $answercodekeysarr = Array($answercodefilednum1,$answercodefilednum2); // $answerssupportbaselang = bDoesImportarraySupportsLanguage($answerarray,$answercodekeysarr,$langfieldnum,$langcode); // if (!$answerssupportbaselang) // { // $importquestion .= "<strong><font color='red'>".("Error")."</font></strong>\n" // .("You can't import answers which don't support current survey's base language")."\n" // ."</td></tr></table>\n"; // return; // } // //} $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); if ($countlabelsets > 0) { $labelsetfieldname = convertCSVRowToArray($labelsetsarray[0], ',', '"'); $langfieldnum = array_search("languages", $labelsetfieldname); $lidfilednum = array_search("lid", $labelsetfieldname); $labelsetssupportbaselang = bDoesImportarraySupportsLanguage($labelsetsarray, array($lidfilednum), $langfieldnum, $langcode, true); if (!$labelsetssupportbaselang) { // $importquestion .= "<strong><font color='red'>".("Error")."</font></strong>\n" // .("You can't import label sets which don't support the current survey's base language")."\n" // ."</td></tr></table>\n"; // unlink($the_full_file_path); return "You can't import label sets which don't support the current survey's base language"; } } // I assume that if a labelset supports the survey's baselang, // then it's labels do support it as well // GET SURVEY AND GROUP DETAILS //$surveyid=$postsid; //$gid=$postgid; $newsid = $surveyid; $newgid = $gid; $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); //DO ANY LABELSETS FIRST, SO WE CAN KNOW WHAT THEIR NEW LID IS FOR THE QUESTIONS if (isset($labelsetsarray) && $labelsetsarray) { $csarray = buildLabelSetCheckSumArray(); // build checksums over all existing labelsets $count = 0; $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); foreach ($labelsetsarray as $lsa) { $fieldorders = convertCSVRowToArray($labelsetsarray[0], ',', '"'); $fieldcontents = convertCSVRowToArray($lsa, ',', '"'); if ($count == 0) { $count++; continue; } $labelsetrowdata = array_combine($fieldorders, $fieldcontents); // Save old labelid $oldlid = $labelsetrowdata['lid']; // set the new language unset($labelsetrowdata['lid']); $newvalues = array_values($labelsetrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $lsainsert = "INSERT INTO {$dbprefix}labelsets (" . implode(',', array_keys($labelsetrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; //handle db prefix $lsiresult = $connect->Execute($lsainsert); // Get the new insert id for the labels inside this labelset $newlid = $connect->Insert_ID("{$dbprefix}labelsets", "lid"); if ($labelsarray) { $count = 0; foreach ($labelsarray as $la) { $lfieldorders = convertCSVRowToArray($labelsarray[0], ',', '"'); $lfieldcontents = convertCSVRowToArray($la, ',', '"'); if ($count == 0) { $count++; continue; } // Combine into one array with keys and values since its easier to handle $labelrowdata = array_combine($lfieldorders, $lfieldcontents); $labellid = $labelrowdata['lid']; if ($labellid == $oldlid) { $labelrowdata['lid'] = $newlid; // translate internal links $labelrowdata['title'] = translink('label', $oldlid, $newlid, $labelrowdata['title']); $newvalues = array_values($labelrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $lainsert = "INSERT INTO {$dbprefix}labels (" . implode(',', array_keys($labelrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; //handle db prefix $liresult = $connect->Execute($lainsert); } } } //CHECK FOR DUPLICATE LABELSETS $thisset = ""; $query2 = "SELECT code, title, sortorder, language\r\n\t\t FROM {$dbprefix}labels\r\n\t\t WHERE lid=" . $newlid . "\r\n\t\t ORDER BY language, sortorder, code"; $result2 = db_execute_num($query2) or $this->debugLsrc("Died querying labelset {$lid}{$query2}" . $connect->ErrorMsg()); while ($row2 = $result2->FetchRow()) { $thisset .= implode('.', $row2); } // while $newcs = dechex(crc32($thisset) * 1); unset($lsmatch); if (isset($csarray)) { foreach ($csarray as $key => $val) { if ($val == $newcs) { $lsmatch = $key; } } } if (isset($lsmatch)) { //There is a matching labelset. So, we will delete this one and refer //to the matched one. $query = "DELETE FROM {$dbprefix}labels WHERE lid={$newlid}"; $result = $connect->Execute($query) or $this->debugLsrc("Couldn't delete labels{$query}" . $connect->ErrorMsg()); $query = "DELETE FROM {$dbprefix}labelsets WHERE lid={$newlid}"; $result = $connect->Execute($query) or $this->debugLsrc("Couldn't delete labelset{$query}" . $connect->ErrorMsg()); $newlid = $lsmatch; } else { //There isn't a matching labelset, add this checksum to the $csarray array $csarray[$newlid] = $newcs; } //END CHECK FOR DUPLICATES $labelreplacements[] = array($oldlid, $newlid); } } $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); // QUESTIONS, THEN ANSWERS FOR QUESTIONS IN A NESTED FORMAT! if (isset($questionarray) && $questionarray) { $qafieldorders = convertCSVRowToArray($questionarray[0], ',', '"'); unset($questionarray[0]); //Assuming we will only import one question at a time we will now find out the maximum question order in this group //and save it for later $qmaxqo = "SELECT MAX(question_order) AS maxqo FROM " . db_table_name('questions') . " WHERE sid={$newsid} AND gid={$newgid}"; $qres = db_execute_assoc($qmaxqo) or $this->debugLsrc("Error: " . ": Failed to find out maximum question order value\n{$qmaxqo}\n" . $connect->ErrorMsg()); $qrow = $qres->FetchRow(); $newquestionorder = $qrow['maxqo'] + 1; $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); foreach ($questionarray as $qa) { $qacfieldcontents = convertCSVRowToArray($qa, ',', '"'); $newfieldcontents = $qacfieldcontents; $questionrowdata = array_combine($qafieldorders, $qacfieldcontents); if (isset($languagesSupported[$questionrowdata["language"]])) { $oldqid = $questionrowdata['qid']; $oldsid = $questionrowdata['sid']; $oldgid = $questionrowdata['gid']; // Remove qid field if there is no newqid; and set it to newqid if it's set if (!isset($newqid)) { unset($questionrowdata['qid']); } else { $questionrowdata['qid'] = $newqid; } $questionrowdata["sid"] = $newsid; $questionrowdata["gid"] = $newgid; $questionrowdata["question_order"] = $newquestionorder; $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); // Now we will fix up the label id $type = $questionrowdata["type"]; //Get the type if ($type == "F" || $type == "H" || $type == "1" || $type == ":" || $type == ";") { //IF this is a flexible label array, update the lid entry $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); if (isset($labelreplacements)) { foreach ($labelreplacements as $lrp) { if ($lrp[0] == $questionrowdata["lid"]) { $questionrowdata["lid"] = $lrp[1]; } if ($lrp[0] == $questionrowdata["lid1"]) { $questionrowdata["lid1"] = $lrp[1]; } } } } $other = $questionrowdata["other"]; //Get 'other' field value $oldlid = $questionrowdata["lid"]; $questionrowdata = array_map('convertCsvreturn2return', $questionrowdata); // translate internal links $questionrowdata['title'] = translink('survey', $oldsid, $newsid, $questionrowdata['title']); $questionrowdata['question'] = translink('survey', $oldsid, $newsid, $questionrowdata['question']); $questionrowdata['help'] = translink('survey', $oldsid, $newsid, $questionrowdata['help']); $newvalues = array_values($questionrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $qinsert = "INSERT INTO {$dbprefix}questions (" . implode(',', array_keys($questionrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; $qres = $connect->Execute($qinsert) or $this->debugLsrc("Error: " . ": Failed to insert question\n{$qinsert}\n" . $connect->ErrorMsg()); $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); // set the newqid only if is not set if (!isset($newqid)) { $newqid = $connect->Insert_ID("{$dbprefix}questions", "qid"); } } } $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); //NOW DO ANSWERS FOR THIS QID - Is called just once and only if there was a question if (isset($answerarray) && $answerarray) { foreach ($answerarray as $aa) { $answerfieldcontents = convertCSVRowToArray($aa, ',', '"'); $answerrowdata = array_combine($answerfieldnames, $answerfieldcontents); if ($answerrowdata === false) { $importquestion .= '' . "Faulty line in import - fields and data don't match" . ":" . implode(',', $answerfieldcontents); } if (isset($languagesSupported[$answerrowdata["language"]])) { $code = $answerrowdata["code"]; $thisqid = $answerrowdata["qid"]; $answerrowdata["qid"] = $newqid; // translate internal links $answerrowdata['answer'] = translink('survey', $oldsid, $newsid, $answerrowdata['answer']); $newvalues = array_values($answerrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $ainsert = "INSERT INTO {$dbprefix}answers (" . implode(',', array_keys($answerrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; $ares = $connect->Execute($ainsert) or $this->debugLsrc("Error: " . ": Failed to insert answer\n{$ainsert}\n" . $connect->ErrorMsg()); } } } $this->debugLsrc("wir sind in " . __FILE__ . " - " . __FUNCTION__ . " Line " . __LINE__ . ", OK "); // Finally the question attributes - Is called just once and only if there was a question if (isset($question_attributesarray) && $question_attributesarray) { //ONLY DO THIS IF THERE ARE QUESTION_ATTRIBUES $fieldorders = convertCSVRowToArray($question_attributesarray[0], ',', '"'); unset($question_attributesarray[0]); foreach ($question_attributesarray as $qar) { $fieldcontents = convertCSVRowToArray($qar, ',', '"'); $qarowdata = array_combine($fieldorders, $fieldcontents); $qarowdata["qid"] = $newqid; unset($qarowdata["qaid"]); $newvalues = array_values($qarowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $qainsert = "INSERT INTO {$dbprefix}question_attributes (" . implode(',', array_keys($qarowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; $result = $connect->Execute($qainsert) or $this->debugLsrc("Couldn't insert question_attribute{$qainsert}" . $connect->ErrorMsg()); } } } $this->debugLsrc("wir sind in - " . __FUNCTION__ . " Line " . __LINE__ . ", FERTIG "); // CONDITIONS is DONE return array('gid' => $newgid, 'qid' => $newqid); //return $newgid; }
/** * This function imports an old-school question file (*.csv,*.sql) * * @param mixed $sFullFilepath Full file patch to the import file * @param mixed $newsid Survey ID to which the question is attached * @param mixed $newgid Group ID top which the question is attached */ function CSVImportQuestion($sFullFilepath, $newsid, $newgid) { global $dbprefix, $connect, $clang; $aLIDReplacements = array(); $aQIDReplacements = array(); // this array will have the "new qid" for the questions, the key will be the "old qid" $aSQIDReplacements = array(); $results['labelsets'] = 0; $results['labels'] = 0; $handle = fopen($sFullFilepath, "r"); while (!feof($handle)) { $buffer = fgets($handle); //To allow for very long survey welcomes (up to 10k) $bigarray[] = $buffer; } fclose($handle); $importversion = 0; // Now we try to determine the dataformat of the survey file. if (substr($bigarray[1], 0, 24) == "# SURVEYOR QUESTION DUMP") { $importversion = 100; // version 1.0 or 0.99 file } elseif (substr($bigarray[0], 0, 26) == "# LimeSurvey Question Dump" || substr($bigarray[0], 0, 27) == "# PHPSurveyor Question Dump") { // This is a >1.0 version file - these files carry the version information to read in line two $importversion = (int) substr($bigarray[1], 12, 3); } else { $results['fatalerror'] = $clang->gT("This file is not a LimeSurvey question file. Import failed."); return $results; } if ((int) $importversion < 112) { $results['fatalerror'] = $clang->gT("This file is too old. Only files from LimeSurvey version 1.50 (DBVersion 112) and newer are supported."); return $results; } for ($i = 0; $i < 9; $i++) { unset($bigarray[$i]); } $bigarray = array_values($bigarray); //QUESTIONS if (array_search("# ANSWERS TABLE\n", $bigarray)) { $stoppoint = array_search("# ANSWERS TABLE\n", $bigarray); } elseif (array_search("# ANSWERS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# ANSWERS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $questionarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //ANSWERS if (array_search("# LABELSETS TABLE\n", $bigarray)) { $stoppoint = array_search("# LABELSETS TABLE\n", $bigarray); } elseif (array_search("# LABELSETS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# LABELSETS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $answerarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //LABELSETS if (array_search("# LABELS TABLE\n", $bigarray)) { $stoppoint = array_search("# LABELS TABLE\n", $bigarray); } elseif (array_search("# LABELS TABLE\r\n", $bigarray)) { $stoppoint = array_search("# LABELS TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $labelsetsarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //LABELS if (array_search("# QUESTION_ATTRIBUTES TABLE\n", $bigarray)) { $stoppoint = array_search("# QUESTION_ATTRIBUTES TABLE\n", $bigarray); } elseif (array_search("# QUESTION_ATTRIBUTES TABLE\r\n", $bigarray)) { $stoppoint = array_search("# QUESTION_ATTRIBUTES TABLE\r\n", $bigarray); } else { $stoppoint = count($bigarray) - 1; } for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 2) { $labelsarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); //Question_attributes $stoppoint = count($bigarray); for ($i = 0; $i <= $stoppoint + 1; $i++) { if ($i < $stoppoint - 1) { $question_attributesarray[] = $bigarray[$i]; } unset($bigarray[$i]); } $bigarray = array_values($bigarray); if (isset($questionarray)) { $questionfieldnames = convertCSVRowToArray($questionarray[0], ',', '"'); unset($questionarray[0]); $countquestions = count($questionarray) - 1; } else { $countquestions = 0; } if (isset($answerarray)) { $answerfieldnames = convertCSVRowToArray($answerarray[0], ',', '"'); unset($answerarray[0]); $countanswers = count($answerarray); } else { $countanswers = 0; } if (isset($labelsetsarray)) { $countlabelsets = count($labelsetsarray) - 1; } else { $countlabelsets = 0; } if (isset($labelsarray)) { $countlabels = count($labelsarray) - 1; } else { $countlabels = 0; } if (isset($question_attributesarray)) { $countquestion_attributes = count($question_attributesarray) - 1; } else { $countquestion_attributes = 0; } $aLanguagesSupported = array(); // this array will keep all the languages supported for the survey $sBaseLanguage = GetBaseLanguageFromSurveyID($newsid); $aLanguagesSupported[] = $sBaseLanguage; // adds the base language to the list of supported languages $aLanguagesSupported = array_merge($aLanguagesSupported, GetAdditionalLanguagesFromSurveyID($newsid)); // Let's check that imported objects support at least the survey's baselang if (isset($questionarray)) { $langfieldnum = array_search("language", $questionfieldnames); $qidfieldnum = array_search("qid", $questionfieldnames); $questionssupportbaselang = bDoesImportarraySupportsLanguage($questionarray, array($qidfieldnum), $langfieldnum, $sBaseLanguage, true); if (!$questionssupportbaselang) { $results['fatalerror'] = $clang->gT("You can't import a question which doesn't support at least the survey base language."); return $results; } } if ($countanswers > 0) { $langfieldnum = array_search("language", $answerfieldnames); $answercodefilednum1 = array_search("qid", $answerfieldnames); $answercodefilednum2 = array_search("code", $answerfieldnames); $answercodekeysarr = array($answercodefilednum1, $answercodefilednum2); $answerssupportbaselang = bDoesImportarraySupportsLanguage($answerarray, $answercodekeysarr, $langfieldnum, $sBaseLanguage); if (!$answerssupportbaselang) { $results['fatalerror'] = $clang->gT("You can't import answers which doesn't support at least the survey base language."); return $results; } } if ($countlabelsets > 0) { $labelsetfieldname = convertCSVRowToArray($labelsetsarray[0], ',', '"'); $langfieldnum = array_search("languages", $labelsetfieldname); $lidfilednum = array_search("lid", $labelsetfieldname); $labelsetssupportbaselang = bDoesImportarraySupportsLanguage($labelsetsarray, array($lidfilednum), $langfieldnum, $sBaseLanguage, true); if (!$labelsetssupportbaselang) { $results['fatalerror'] = $clang->gT("You can't import label sets which don't support the current survey's base language"); return $results; } } // I assume that if a labelset supports the survey's baselang, // then it's labels do support it as well //DO ANY LABELSETS FIRST, SO WE CAN KNOW WHAT THEIR NEW LID IS FOR THE QUESTIONS if (isset($labelsetsarray) && $labelsetsarray) { $csarray = buildLabelSetCheckSumArray(); // build checksums over all existing labelsets $count = 0; foreach ($labelsetsarray as $lsa) { $fieldorders = convertCSVRowToArray($labelsetsarray[0], ',', '"'); $fieldcontents = convertCSVRowToArray($lsa, ',', '"'); if ($count == 0) { $count++; continue; } $results['labelsets']++; $labelsetrowdata = array_combine($fieldorders, $fieldcontents); // Save old labelid $oldlid = $labelsetrowdata['lid']; // set the new language unset($labelsetrowdata['lid']); $newvalues = array_values($labelsetrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $lsainsert = "INSERT INTO {$dbprefix}labelsets (" . implode(',', array_keys($labelsetrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; //handle db prefix $lsiresult = $connect->Execute($lsainsert); // Get the new insert id for the labels inside this labelset $newlid = $connect->Insert_ID("{$dbprefix}labelsets", 'lid'); if ($labelsarray) { $count = 0; foreach ($labelsarray as $la) { $lfieldorders = convertCSVRowToArray($labelsarray[0], ',', '"'); $lfieldcontents = convertCSVRowToArray($la, ',', '"'); if ($count == 0) { $count++; continue; } // Combine into one array with keys and values since its easier to handle $labelrowdata = array_combine($lfieldorders, $lfieldcontents); $labellid = $labelrowdata['lid']; if ($importversion <= 132) { $labelrowdata["assessment_value"] = (int) $labelrowdata["code"]; } if ($labellid == $oldlid) { $labelrowdata['lid'] = $newlid; // translate internal links $labelrowdata['title'] = translink('label', $oldlid, $newlid, $labelrowdata['title']); $newvalues = array_values($labelrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $lainsert = "INSERT INTO {$dbprefix}labels (" . implode(',', array_keys($labelrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; //handle db prefix $liresult = $connect->Execute($lainsert); $results['labels']++; } } } //CHECK FOR DUPLICATE LABELSETS $thisset = ""; $query2 = "SELECT code, title, sortorder, language, assessment_value\n FROM {$dbprefix}labels\n WHERE lid=" . $newlid . "\n ORDER BY language, sortorder, code"; $result2 = db_execute_num($query2) or safe_die("Died querying labelset {$lid}<br />{$query2}<br />" . $connect->ErrorMsg()); while ($row2 = $result2->FetchRow()) { $thisset .= implode('.', $row2); } // while $newcs = dechex(crc32($thisset) * 1); unset($lsmatch); if (isset($csarray)) { foreach ($csarray as $key => $val) { if ($val == $newcs) { $lsmatch = $key; } } } if (isset($lsmatch)) { //There is a matching labelset. So, we will delete this one and refer //to the matched one. $query = "DELETE FROM {$dbprefix}labels WHERE lid={$newlid}"; $result = $connect->Execute($query) or safe_die("Couldn't delete labels<br />{$query}<br />" . $connect->ErrorMsg()); $query = "DELETE FROM {$dbprefix}labelsets WHERE lid={$newlid}"; $result = $connect->Execute($query) or safe_die("Couldn't delete labelset<br />{$query}<br />" . $connect->ErrorMsg()); $newlid = $lsmatch; } else { //There isn't a matching labelset, add this checksum to the $csarray array $csarray[$newlid] = $newcs; } //END CHECK FOR DUPLICATES $aLIDReplacements[$oldlid] = $newlid; } } // Import questions if (isset($questionarray) && $questionarray) { //Assuming we will only import one question at a time we will now find out the maximum question order in this group //and save it for later $newquestionorder = $connect->GetOne("SELECT MAX(question_order) AS maxqo FROM " . db_table_name('questions') . " WHERE sid={$newsid} AND gid={$newgid}"); if (is_null($newquestionorder)) { $newquestionorder = 0; } else { $newquestionorder++; } foreach ($questionarray as $qa) { $qacfieldcontents = convertCSVRowToArray($qa, ',', '"'); $questionrowdata = array_combine($questionfieldnames, $qacfieldcontents); // Skip not supported languages if (!in_array($questionrowdata['language'], $aLanguagesSupported)) { continue; } // replace the sid $oldqid = $questionrowdata['qid']; $oldsid = $questionrowdata['sid']; $oldgid = $questionrowdata['gid']; // Remove qid field if there is no newqid; and set it to newqid if it's set if (!isset($newqid)) { unset($questionrowdata['qid']); } else { db_switchIDInsert('questions', true); $questionrowdata['qid'] = $newqid; } $questionrowdata["sid"] = $newsid; $questionrowdata["gid"] = $newgid; $questionrowdata["question_order"] = $newquestionorder; // Save the following values - will need them for proper conversion later if ((int)$questionrowdata['lid']>0) if ((int) $questionrowdata['lid'] > 0) { $oldquestion['lid1'] = (int) $questionrowdata['lid']; } if ((int) $questionrowdata['lid1'] > 0) { $oldquestion['lid2'] = (int) $questionrowdata['lid1']; } $oldquestion['oldtype'] = $questionrowdata['type']; // Unset label set IDs and convert question types unset($questionrowdata['lid']); unset($questionrowdata['lid1']); if ($questionrowdata['type'] == 'W') { $questionrowdata['type'] = '!'; } elseif ($questionrowdata['type'] == 'Z') { $questionrowdata['type'] = 'L'; } $oldquestion['newtype'] = $questionrowdata['type']; $questionrowdata = array_map('convertCsvreturn2return', $questionrowdata); // translate internal links $questionrowdata['title'] = translink('survey', $oldsid, $newsid, $questionrowdata['title']); $questionrowdata['question'] = translink('survey', $oldsid, $newsid, $questionrowdata['question']); $questionrowdata['help'] = translink('survey', $oldsid, $newsid, $questionrowdata['help']); $newvalues = array_values($questionrowdata); $newvalues = array_map(array(&$connect, "qstr"), $newvalues); // quote everything accordingly $qinsert = "INSERT INTO {$dbprefix}questions (" . implode(',', array_keys($questionrowdata)) . ") VALUES (" . implode(',', $newvalues) . ")"; $qres = $connect->Execute($qinsert) or safe_die("Error: Failed to insert question<br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); // set the newqid only if is not set if (!isset($newqid)) { $newqid = $connect->Insert_ID("{$dbprefix}questions", "qid"); } else { db_switchIDInsert('questions', false); } } $qtypes = getqtypelist("", "array"); $results['answers'] = 0; $results['subquestions'] = 0; // Now we will fix up old label sets where they are used as answers if ((isset($oldquestion['lid1']) || isset($oldquestion['lid2'])) && ($qtypes[$oldquestion['newtype']]['answerscales'] > 0 || $qtypes[$oldquestion['newtype']]['subquestions'] > 1)) { $query = "select * from " . db_table_name('labels') . " where lid={$aLIDReplacements[$oldquestion['lid1']]} "; $oldlabelsresult = db_execute_assoc($query); while ($labelrow = $oldlabelsresult->FetchRow()) { if (in_array($labelrow['language'], $aLanguagesSupported)) { if ($qtypes[$oldquestion['newtype']]['subquestions'] < 2) { $qinsert = "insert INTO " . db_table_name('answers') . " (qid,code,answer,sortorder,language,assessment_value,scale_id)\n VALUES ({$newqid}," . db_quoteall($labelrow['code']) . "," . db_quoteall($labelrow['title']) . "," . db_quoteall($labelrow['sortorder']) . "," . db_quoteall($labelrow['language']) . "," . db_quoteall($labelrow['assessment_value']) . ",0)"; $qres = $connect->Execute($qinsert) or safe_die("Error: Failed to insert answer <br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); $results['answers']++; } else { if (isset($aSQIDReplacements[$labelrow['code']])) { $fieldname = 'qid,'; $data = $aSQIDReplacements[$labelrow['code']] . ','; db_switchIDInsert('questions', true); } else { $fieldname = ''; $data = ''; } $qinsert = "insert INTO " . db_table_name('questions') . " ({$fieldname} sid,gid,parent_qid,title,question,question_order,language,scale_id,type)\n VALUES ({$data} {$newsid},{$newgid},{$newqid}," . db_quoteall($labelrow['code']) . "," . db_quoteall($labelrow['title']) . "," . db_quoteall($labelrow['sortorder']) . "," . db_quoteall($labelrow['language']) . ",1," . db_quoteall($oldquestion['newtype']) . ")"; $qres = $connect->Execute($qinsert) or safe_die("Error: Failed to insert subquestion <br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); if ($fieldname == '') { $aSQIDReplacements[$labelrow['code']] = $connect->Insert_ID("{$dbprefix}questions", "qid"); } else { db_switchIDInsert('questions', false); } } } } if (isset($oldquestion['lid2']) && $qtypes[$oldquestion['newtype']]['answerscales'] > 1) { $query = "select * from " . db_table_name('labels') . " where lid={$aLIDReplacements[$oldquestion['lid2']]}"; $oldlabelsresult = db_execute_assoc($query); while ($labelrow = $oldlabelsresult->FetchRow()) { if (in_array($labelrow['language'], $aLanguagesSupported)) { $qinsert = "insert INTO " . db_table_name('answers') . " (qid,code,answer,sortorder,language,assessment_value,scale_id)\n VALUES ({$newqid}," . db_quoteall($labelrow['code']) . "," . db_quoteall($labelrow['title']) . "," . db_quoteall($labelrow['sortorder']) . "," . db_quoteall($labelrow['language']) . "," . db_quoteall($labelrow['assessment_value']) . ",1)"; $qres = $connect->Execute($qinsert) or safe_die($clang->gT("Error") . ": Failed to insert answer <br />\n{$qinsert}<br />\n" . $connect->ErrorMsg()); } } } } //Do answers if (isset($answerarray) && $answerarray) { foreach ($answerarray as $aa) { $answerfieldcontents = convertCSVRowToArray($aa, ',', '"'); $answerrowdata = array_combine($answerfieldnames, $answerfieldcontents); if ($answerrowdata === false) { $importquestion .= '<br />' . $clang->gT("Faulty line in import - fields and data don't match") . ":" . implode(',', $answerfieldcontents); } // Skip not supported languages if (!in_array($answerrowdata['language'], $aLanguagesSupported)) { continue; } $code = $answerrowdata["code"]; $thisqid = $answerrowdata["qid"]; $answerrowdata["qid"] = $newqid; if ($importversion <= 132) { $answerrowdata["assessment_value"] = (int) $answerrowdata["code"]; } // Convert default values for single select questions if ($answerrowdata['default_value'] == 'Y' && ($oldquestion['newtype'] == 'L' || $oldquestion['newtype'] == 'O' || $oldquestion['newtype'] == '!')) { $insertdata = array(); $insertdata['qid'] = $newqid; $insertdata['language'] = $answerrowdata['language']; $insertdata['defaultvalue'] = $answerrowdata['answer']; $query = $connect->GetInsertSQL($dbprefix . 'defaultvalues', $insertdata); $qres = $connect->Execute($query) or safe_die("Error: Failed to insert defaultvalue <br />{$query}<br />\n" . $connect->ErrorMsg()); } // translate internal links $answerrowdata['answer'] = translink('survey', $oldsid, $newsid, $answerrowdata['answer']); // Everything set - now insert it $answerrowdata = array_map('convertCsvreturn2return', $answerrowdata); if ($qtypes[$oldquestion['newtype']]['subquestions'] > 0) { $questionrowdata = array(); if (isset($aSQIDReplacements[$answerrowdata['code'] . $answerrowdata['qid']])) { $questionrowdata['qid'] = $aSQIDReplacements[$answerrowdata['code'] . $answerrowdata['qid']]; db_switchIDInsert('questions', true); } $questionrowdata['parent_qid'] = $answerrowdata['qid']; $questionrowdata['sid'] = $newsid; $questionrowdata['gid'] = $newgid; $questionrowdata['title'] = $answerrowdata['code']; $questionrowdata['question'] = $answerrowdata['answer']; $questionrowdata['question_order'] = $answerrowdata['sortorder']; $questionrowdata['language'] = $answerrowdata['language']; $questionrowdata['type'] = $oldquestion['newtype']; $tablename = $dbprefix . 'questions'; $query = $connect->GetInsertSQL($tablename, $questionrowdata); $qres = $connect->Execute($query) or safe_die("Error: Failed to insert question <br />{$query}<br />\n" . $connect->ErrorMsg()); if (!isset($questionrowdata['qid'])) { $aSQIDReplacements[$answerrowdata['code'] . $answerrowdata['qid']] = $connect->Insert_ID("{$dbprefix}questions", "qid"); } else { db_switchIDInsert('questions', false); } $results['subquestions']++; // also convert default values subquestions for multiple choice if ($answerrowdata['default_value'] == 'Y' && ($oldquestion['newtype'] == 'M' || $oldquestion['newtype'] == 'P')) { $insertdata = array(); $insertdata['qid'] = $newqid; $insertdata['sqid'] = $aSQIDReplacements[$answerrowdata['code']]; $insertdata['language'] = $answerrowdata['language']; $insertdata['defaultvalue'] = 'Y'; $tablename = $dbprefix . 'defaultvalues'; $query = $connect->GetInsertSQL($tablename, $insertdata); $qres = $connect->Execute($query) or safe_die("Error: Failed to insert defaultvalue <br />{$query}<br />\n" . $connect->ErrorMsg()); } } else { unset($answerrowdata['default_value']); $tablename = $dbprefix . 'answers'; $query = $connect->GetInsertSQL($tablename, $answerrowdata); $ares = $connect->Execute($query) or safe_die("Error: Failed to insert answer<br />{$query}<br />\n" . $connect->ErrorMsg()); $results['answers']++; } } } $results['question_attributes'] = 0; // Finally the question attributes - it is called just once and only if there was a question if (isset($question_attributesarray) && $question_attributesarray) { //ONLY DO THIS IF THERE ARE QUESTION_ATTRIBUES $fieldorders = convertCSVRowToArray($question_attributesarray[0], ',', '"'); unset($question_attributesarray[0]); foreach ($question_attributesarray as $qar) { $fieldcontents = convertCSVRowToArray($qar, ',', '"'); $qarowdata = array_combine($fieldorders, $fieldcontents); $qarowdata["qid"] = $newqid; unset($qarowdata["qaid"]); $tablename = "{$dbprefix}question_attributes"; $qainsert = $connect->GetInsertSQL($tablename, $qarowdata); $result = $connect->Execute($qainsert) or safe_die("Couldn't insert question_attribute<br />{$qainsert}<br />" . $connect->ErrorMsg()); $results['question_attributes']++; } } } LimeExpressionManager::SetDirtyFlag(); // so refreshes syntax highlighting $results['newqid'] = $newqid; $results['questions'] = 1; $results['newqid'] = $newqid; return $results; }