View Issue Details

This bug affects 1 person(s).
 4
IDProjectCategoryView StatusLast Update
04739Bug reportsImport/Exportpublic2010-12-07 14:14
Reporteruser1329Assigned Toc_schmitz  
PrioritynormalSeveritypartial_block 
Status closedResolutionfixed 
Product Version1.90+ 
Summary04739: Exported survey lss file does not import
Description

I exported the attached survey file from a running (production environment) lime instance.
When I wanted to reimport it into another lime instance (quality environment), it never reached the end of the import.
The structure of the lss file looks ok.
Both environments are the same i.e. same lime release, same php instance, same IIS instance, same database driver (mssqlnative) and same version of mssql server.

Steps To Reproduce

1- take attached lss file and try to import it.
2- importing process runs without stopping until error.

Additional Information

I have no clue whether the problem comes from the export process which produces a faulty lss file or whether it comes from the import process that has problems handling the lss file.

TagsNo tags attached.
Attached Files
export_structure_xml.php (7,682 bytes)   
<?php
/*
 * LimeSurvey
 * Copyright (C) 2007 The LimeSurvey Project Team / Carsten Schmitz
 * All rights reserved.
 * License: GNU/GPL License v2 or later, see LICENSE.php
 * LimeSurvey is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 *
 * $Id: export_structure_csv.php 8592 2010-04-14 12:23:25Z machaven $
 */



// DUMP THE RELATED DATA FOR A SINGLE SURVEY INTO AN XML FILE FOR IMPORTING LATER ON OR ON ANOTHER SURVEY SETUP
// DUMP ALL DATA FOR RELATED SID FROM THE FOLLOWING TABLES:
// Answers
// Assessments
// Conditions
// Default values
// Groups
// Questions
// Question attributes
// Quota
// Quota Members
// Surveys
// Surveys language settings

include_once("login_check.php");
require_once ("export_data_functions.php");

if (!isset($surveyid))
{
    $surveyid=returnglobal('sid');
}


if (!$surveyid)
{
    echo $htmlheader
    ."<br />\n"
    ."<table width='350' align='center' style='border: 1px solid #555555' cellpadding='1' cellspacing='0'>\n"
    ."\t<tr bgcolor='#555555'><td colspan='2' height='4'><font size='1' face='verdana' color='white'><strong>"
    .$clang->gT("Export Survey")."</strong></td></tr>\n"
    ."\t<tr><td align='center'>\n"
    ."<br /><strong><font color='red'>"
    .$clang->gT("Error")."</font></strong><br />\n"
    .$clang->gT("No SID has been provided. Cannot dump survey")."<br />\n"
    ."<br /><input type='submit' value='"
    .$clang->gT("Main Admin Screen")."' onclick=\"window.open('$scriptname', '_top')\">\n"
    ."\t</td></tr>\n"
    ."</table>\n"
    ."</body></html>\n";
    exit;
}

function getXMLStructure($xmlwriter, $exclude=array())
{
    global $dbprefix, $surveyid, $connect;

    $sdump = "";

    if ((!isset($exclude) && $exclude['answers'] !== true) || empty($exclude))
    {
        //Answers table
        $aquery = "SELECT {$dbprefix}answers.*
           FROM {$dbprefix}answers, {$dbprefix}questions 
		   WHERE {$dbprefix}answers.language={$dbprefix}questions.language 
		   AND {$dbprefix}answers.qid={$dbprefix}questions.qid 
		   AND {$dbprefix}questions.sid=$surveyid";
        BuildXMLFromQuery($xmlwriter,$aquery);
    }

    // Assessments
    $query = "SELECT {$dbprefix}assessments.*
          FROM {$dbprefix}assessments 
          WHERE {$dbprefix}assessments.sid=$surveyid";
    BuildXMLFromQuery($xmlwriter,$query);
    
    if ((!isset($exclude) && $exclude['conditions'] !== true) || empty($exclude))
    {
        //Conditions table
        $cquery = "SELECT DISTINCT {$dbprefix}conditions.*
           FROM {$dbprefix}conditions, {$dbprefix}questions 
		   WHERE {$dbprefix}conditions.qid={$dbprefix}questions.qid 
		   AND {$dbprefix}questions.sid=$surveyid";
        BuildXMLFromQuery($xmlwriter,$cquery);
    }

    //Default values
    $query = "SELECT {$dbprefix}defaultvalues.*
          FROM {$dbprefix}defaultvalues JOIN {$dbprefix}questions ON {$dbprefix}questions.qid = {$dbprefix}defaultvalues.qid AND {$dbprefix}questions.sid=$surveyid AND {$dbprefix}questions.language={$dbprefix}defaultvalues.language "; 
    
    BuildXMLFromQuery($xmlwriter,$query);
    
    // Groups 
    $gquery = "SELECT *
           FROM {$dbprefix}groups 
           WHERE sid=$surveyid 
           ORDER BY gid";
    BuildXMLFromQuery($xmlwriter,$gquery);
    
    //Questions    
    $qquery = "SELECT *
           FROM {$dbprefix}questions 
           WHERE sid=$surveyid and parent_qid=0 
           ORDER BY qid";
    BuildXMLFromQuery($xmlwriter,$qquery);

    //Subquestions    
    $qquery = "SELECT *
           FROM {$dbprefix}questions 
           WHERE sid=$surveyid and parent_qid>0
           ORDER BY qid";
    BuildXMLFromQuery($xmlwriter,$qquery,'subquestions');
    
    //Question attributes
    $sBaseLanguage=GetBaseLanguageFromSurveyID($surveyid);
    if ($connect->databaseType == 'odbc_mssql' || $connect->databaseType == 'odbtp' || $connect->databaseType == 'mssql_n' || $connect->databaseType =='mssqlnative')
    {
        $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value 
          FROM {$dbprefix}question_attributes qa JOIN {$dbprefix}questions  q ON q.qid = qa.qid AND q.sid={$surveyid} 
          where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute,  cast(qa.value as varchar(4000))";
    }
    else {
        $query="SELECT qa.qid, qa.attribute, qa.value
          FROM {$dbprefix}question_attributes qa JOIN {$dbprefix}questions  q ON q.qid = qa.qid AND q.sid={$surveyid} 
          where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value";
    }
    
    BuildXMLFromQuery($xmlwriter,$query,'question_attributes');

    if ((!isset($exclude) && $exclude['quotas'] !== true) || empty($exclude))
    {
        //Quota
        $query = "SELECT {$dbprefix}quota.*
          FROM {$dbprefix}quota 
		  WHERE {$dbprefix}quota.sid=$surveyid";
        BuildXMLFromQuery($xmlwriter,$query);

        //1Quota members
        $query = "SELECT {$dbprefix}quota_members.*
          FROM {$dbprefix}quota_members 
		  WHERE {$dbprefix}quota_members.sid=$surveyid";
        BuildXMLFromQuery($xmlwriter,$query);

        //Quota languagesettings
        $query = "SELECT {$dbprefix}quota_languagesettings.*
          FROM {$dbprefix}quota_languagesettings, {$dbprefix}quota
		  WHERE {$dbprefix}quota.id = {$dbprefix}quota_languagesettings.quotals_quota_id
		  AND {$dbprefix}quota.sid=$surveyid";
        BuildXMLFromQuery($xmlwriter,$query);
    }
    
    // Surveys 
    $squery = "SELECT *
           FROM {$dbprefix}surveys 
           WHERE sid=$surveyid";
    //Exclude some fields from the export
    BuildXMLFromQuery($xmlwriter,$squery,'',array('owner_id','active','datecreated'));

    // Survey language settings 
    $slsquery = "SELECT *
             FROM {$dbprefix}surveys_languagesettings 
             WHERE surveyls_survey_id=$surveyid";
    BuildXMLFromQuery($xmlwriter,$slsquery);
    
}

function getXMLData($exclude = array())
{
    global $dbversionnumber,$surveyid;
    $xml = getXMLWriter();
    $xml->openMemory();
    $xml->setIndent(true);
    $xml->startDocument('1.0', 'UTF-8');
    $xml->startElement('document');
    $xml->writeElement('LimeSurveyDocType','Survey');    
    $xml->writeElement('DBVersion',$dbversionnumber);
    $xml->startElement('languages');
    $surveylanguages=GetAdditionalLanguagesFromSurveyID($surveyid);
    $surveylanguages[]=GetBaseLanguageFromSurveyID($surveyid);
    foreach ($surveylanguages as $surveylanguage)   
    {
        $xml->writeElement('language',$surveylanguage);    
    }
    $xml->endElement();    
    getXMLStructure($xml,$exclude);
    $xml->endElement(); // close columns
    $xml->endDocument();
    return $xml->outputMemory(true);
}

if (!isset($copyfunction))
{
    $fn = "limesurvey_survey_$surveyid.lss";      
    header("Content-Type: text/html/force-download");
    header("Content-Disposition: attachment; filename=$fn");
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");    // Date in the past
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Pragma: cache");                          // HTTP/1.0
    echo getXMLData();
    exit;
}
?>
export_structure_xml.php (7,682 bytes)   
limesurvey_group_338.lsg (361,591 bytes)
dumpquestion.php (4,959 bytes)   
<?php
/*
 * LimeSurvey
 * Copyright (C) 2007 The LimeSurvey Project Team / Carsten Schmitz
 * All rights reserved.
 * License: GNU/GPL License v2 or later, see LICENSE.php
 * LimeSurvey is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 *
 * $Id: dumpquestion.php 9499 2010-11-18 02:06:13Z c_schmitz $
 */



// DUMP THE RELATED DATA FOR A SINGLE QUESTION INTO A SQL FILE FOR IMPORTING LATER ON OR
// ON ANOTHER SURVEY SETUP DUMP ALL DATA WITH RELATED QID FROM THE FOLLOWING TABLES
//  - Questions
//  - Answers
//  - Question attributes
//  - Default values

//Ensure script is not run directly, avoid path disclosure
if (!isset($dbprefix) || isset($_REQUEST['dbprefix'])) {die("Cannot run this script directly");}
include_once("login_check.php");
require_once("export_data_functions.php");      
if(!bHasRight($surveyid,'export')) safe_die("You are not allowed to export questions.");
 

$qid = returnglobal('qid');

if (!$qid)
{
    safe_die("No QID has been provided. Cannot dump question.");
}

$fn = "limesurvey_question_$qid.lsq";      
$xml = getXMLWriter();  

if($action=='exportstructureLsrcCsvQuestion')
{
    include_once($homedir.'/remotecontrol/lsrc.config.php');
    //Select title as Filename and save
    $questionTitleSql = "SELECT title
                     FROM {$dbprefix}questions 
                     WHERE qid=$qid AND sid=$surveyid AND gid=$gid ";
    $questionTitle = $connect->GetOne($questionTitleSql);
    $xml->openURI('remotecontrol/'.$queDir.substr($questionTitle,0,20).".lsq");     
}
else
{
    header("Content-Type: text/html/force-download");
    header("Content-Disposition: attachment; filename=$fn");
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");    // Date in the past
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Pragma: cache");                          // HTTP/1.0

    $xml->openURI('php://output');
}

$xml->setIndent(true);
$xml->startDocument('1.0', 'UTF-8');
$xml->startElement('document');
$xml->writeElement('LimeSurveyDocType','Question');    
$xml->writeElement('DBVersion',$dbversionnumber);    
$xml->startElement('languages');
$lquery = "SELECT language
           FROM {$dbprefix}questions 
           WHERE qid=$qid or parent_qid=$qid group by language";
$lresult=db_execute_assoc($lquery);           
while ($row=$lresult->FetchRow())   
{
    $xml->writeElement('language',$row['language']);    
}
$xml->endElement();
getXMLStructure($xml,$qid);
$xml->endElement(); // close columns
$xml->endDocument();
exit;

function getXMLStructure($xml,$qid)
{
    global $dbprefix, $connect;
    // Questions table
    $qquery = "SELECT *
               FROM {$dbprefix}questions 
               WHERE qid=$qid and parent_qid=0 order by language, scale_id, question_order";
    BuildXMLFromQuery($xml,$qquery);

    // Questions table - Subquestions
    $qquery = "SELECT *
               FROM {$dbprefix}questions 
               WHERE parent_qid=$qid order by language, scale_id, question_order";
    BuildXMLFromQuery($xml,$qquery,'subquestions');
    
    
    // Answers table
    $aquery = "SELECT *
               FROM {$dbprefix}answers 
               WHERE qid = $qid order by language, scale_id, sortorder";
    BuildXMLFromQuery($xml,$aquery);

    
    
    // Question attributes
    $surveyid=$connect->GetOne("select sid from {$dbprefix}questions where qid={$qid}");
    $sBaseLanguage=GetBaseLanguageFromSurveyID($surveyid);
    if ($connect->databaseType == 'odbc_mssql' || $connect->databaseType == 'odbtp' || $connect->databaseType == 'mssql_n' || $connect->databaseType =='mssqlnative')
    {
        $query="SELECT qa.qid, qa.attribute, cast(qa.value as varchar(4000)) as value 
          FROM {$dbprefix}question_attributes qa JOIN {$dbprefix}questions  q ON q.qid = qa.qid AND q.sid={$surveyid} and q.qid={$qid} 
          where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute,  cast(qa.value as varchar(4000))";
    }
    else {
        $query="SELECT qa.qid, qa.attribute, qa.value
          FROM {$dbprefix}question_attributes qa JOIN {$dbprefix}questions  q ON q.qid = qa.qid AND q.sid={$surveyid} and q.qid={$qid}         
          where q.language='{$sBaseLanguage}' group by qa.qid, qa.attribute, qa.value";
    }
    BuildXMLFromQuery($xml,$query);

    // Default values
    $query = "SELECT *
              FROM {$dbprefix}defaultvalues 
              WHERE qid=$qid  order by language, scale_id";
    BuildXMLFromQuery($xml,$query);              

}

dumpquestion.php (4,959 bytes)   
importgroup.php (53,747 bytes)   
<?php
/*
 * LimeSurvey
 * Copyright (C) 2007 The LimeSurvey Project Team / Carsten Schmitz
 * All rights reserved.
 * License: GNU/GPL License v2 or later, see LICENSE.php
 * LimeSurvey is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 *
 * $Id: importgroup.php 9503 2010-11-18 13:34:17Z c_schmitz $
 */

//Ensure script is not run directly, avoid path disclosure 
include_once("login_check.php");

$importgroup = "<div class='header'>".$clang->gT("Import question group")."</div>\n";
$importgroup .= "<div class='messagebox'>\n";

$sFullFilepath = $tempdir . DIRECTORY_SEPARATOR . $_FILES['the_file']['name'];
$aPathInfo = pathinfo($sFullFilepath);
$sExtension = $aPathInfo['extension'];

if (!@move_uploaded_file($_FILES['the_file']['tmp_name'], $sFullFilepath))
{
    $fatalerror = sprintf ($clang->gT("An error occurred uploading your file. This may be caused by incorrect permissions in your %s folder."),$tempdir);
}

// validate that we have a SID
if (!returnglobal('sid'))
{
    $fatalerror .= $clang->gT("No SID (Survey) has been provided. Cannot import question.");
}
else
{
    $surveyid=returnglobal('sid');
}

if (isset($fatalerror))
{
    $importgroup .= "<div class='warningheader'>".$clang->gT("Error")."</div><br />\n";
    $importgroup .= $fatalerror."<br /><br />\n";
    $importgroup .= "<input type='submit' value='".$clang->gT("Main Admin Screen")."' onclick=\"window.open('$scriptname', '_top')\" /><br /><br />\n";
    $importgroup .= "</div>\n";
    @unlink($sFullFilepath);
    return;
}

// IF WE GOT THIS FAR, THEN THE FILE HAS BEEN UPLOADED SUCCESFULLY
$importgroup .= "<div class='successheader'>".$clang->gT("Success")."</div>&nbsp;<br />\n"
.$clang->gT("File upload succeeded.")."<br /><br />\n"
.$clang->gT("Reading file..")."<br /><br />\n";
if (strtolower($sExtension)=='csv')
{
    $aImportResults=CSVImportGroup($sFullFilepath, $surveyid);
}
elseif (strtolower($sExtension)=='lsg')
{
    $aImportResults=XMLImportGroup($sFullFilepath, $surveyid);
}
else die('Unknown file extension');
FixLanguageConsistency($surveyid);

if (isset($aImportResults['fatalerror']))
{
        $importgroup .= "<div class='warningheader'>".$clang->gT("Error")."</div><br />\n";
        $importgroup .= $aImportResults['fatalerror']."<br /><br />\n";
        $importgroup .= "<input type='submit' value='".$clang->gT("Main Admin Screen")."' onclick=\"window.open('$scriptname', '_top')\" />\n";
        $importgroup .=  "</div>\n";
        unlink($sFullFilepath);
        return;
}

$importgroup .= "<div class='successheader'>".$clang->gT("Success")."</div><br />\n"
."<strong><u>".$clang->gT("Question group import summary")."</u></strong><br />\n"
."<ul style=\"text-align:left;\">\n"
."\t<li>".$clang->gT("Groups").": ".$aImportResults['groups']."</li>\n"
."\t<li>".$clang->gT("Questions").": ".$aImportResults['questions']."</li>\n"
."\t<li>".$clang->gT("Subquestions").": ".$aImportResults['subquestions']."</li>\n"
."\t<li>".$clang->gT("Answers").": ".$aImportResults['answers']."</li>\n"
."\t<li>".$clang->gT("Conditions").": ".$aImportResults['conditions']."</li>\n";
if (strtolower($sExtension)=='csv')  {
    $importgroup.="\t<li>".$clang->gT("Label sets").": ".$aImportResults['labelsets']." (".$aImportResults['labels'].")</li>\n";
}
$importgroup.="\t<li>".$clang->gT("Question attributes:").$aImportResults['question_attributes']."</li>"
."</ul>\n";

$importgroup .= "<strong>".$clang->gT("Question group import is complete.")."</strong><br />&nbsp;\n";
$importgroup .= "<input type='submit' value='".$clang->gT("Go to question group")."' onclick=\"window.open('$scriptname?sid=$surveyid&amp;gid={$aImportResults['newgid']}', '_top')\" />\n";
$importgroup .= "</div><br />\n";

unlink($sFullFilepath);


/**
* 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++) //skipping the first lines that are not needed
    {
        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
                       FROM {$dbprefix}labels
                       WHERE lid=".$newlid."
                       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)
                                        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)
                                        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)
                                    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) //hmmm.. this is really a subquestion
            {
                $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   // insert answers
            {
                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']++;
        }
    }
    $results['groups']=1;
    $results['newgid']=$newgid;
    return $results;          
}


/**
* This function imports a LimeSurvey .lsg question group XML file
* 
* @param mixed $sFullFilepath  The full filepath of the uploaded file
* @param mixed $newsid The new survey id - the group will always be added after the last group in the survey   
*/
function XMLImportGroup($sFullFilepath, $newsid)
{
    global $connect, $dbprefix, $clang;
    $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));
    
    $xml = @simplexml_load_file($sFullFilepath);    
    if ($xml==false || $xml->LimeSurveyDocType!='Group') safe_die('This is not a valid LimeSurvey group structure XML file.');
    $dbversion = (int) $xml->DBVersion;
    $aQIDReplacements=array();     
    $results['defaultvalues']=0;
    $results['answers']=0;
    $results['question_attributes']=0;
    $results['subquestions']=0;
    $results['conditions']=0;
    $results['groups']=0;
    
    $importlanguages=array();
    foreach ($xml->languages->language as $language)
    {
        $importlanguages[]=(string)$language;
    }     

    if (!in_array($sBaseLanguage,$importlanguages))
    {
        $results['fatalerror'] = $clang->gT("The languages of the imported group file must at least include the base language of this survey.");
        return;
    }
    // First get an overview of fieldnames - it's not useful for the moment but might be with newer versions
    /*
    $fieldnames=array();
    foreach ($xml->questions->fields->fieldname as $fieldname )
    {
        $fieldnames[]=(string)$fieldname;
    };*/
    
                           
    // Import group table ===================================================================================

    $tablename=$dbprefix.'groups';

    $newgrouporder=$connect->GetOne("SELECT MAX(group_order) AS maxqo FROM ".db_table_name('groups')." WHERE sid=$newsid");
    if (is_null($newgrouporder)) 
    {
        $newgrouporder=0;
    }
    else {
        $newgrouporder++;
    }
    foreach ($xml->groups->rows->row as $row)
    {
       $insertdata=array(); 
        foreach ($row as $key=>$value)
        {
            $insertdata[(string)$key]=(string)$value;
        }
        $oldsid=$insertdata['sid'];
        $insertdata['sid']=$newsid;
        $insertdata['group_order']=$newgrouporder;
        $oldgid=$insertdata['gid']; unset($insertdata['gid']); // save the old qid

        // now translate any links
        $insertdata['group_name']=translink('survey', $oldsid, $newsid, $insertdata['group_name']);
        $insertdata['description']=translink('survey', $oldsid, $newsid, $insertdata['description']);
        // Insert the new question    
        if (isset($aGIDReplacements[$oldgid]))
        {
           $insertdata['gid']=$aGIDReplacements[$oldgid]; 
           db_switchIDInsert('groups',true);
        }   
        $query=$connect->GetInsertSQL($tablename,$insertdata); 
        $result = $connect->Execute($query) or safe_die ($clang->gT("Error").": Failed to insert data<br />{$query}<br />\n".$connect->ErrorMsg());
       $results['groups']++;
        
        if (!isset($aGIDReplacements[$oldgid]))
        {
            $newgid=$connect->Insert_ID($tablename,"gid"); // save this for later
            $aGIDReplacements[$oldgid]=$newgid; // add old and new qid to the mapping array
        }
        else
        {
            db_switchIDInsert('groups',false);
        }
    }
                           
                                                                                      
    // Import questions table ===================================================================================

    // We have to run the question table data two times - first to find all main questions
    // then for subquestions (because we need to determine the new qids for the main questions first)
    $tablename=$dbprefix.'questions';
    $results['questions']=0;
    foreach ($xml->questions->rows->row as $row)
    {
       $insertdata=array(); 
        foreach ($row as $key=>$value)
        {
            $insertdata[(string)$key]=(string)$value;
        }
        $oldsid=$insertdata['sid'];
        $insertdata['sid']=$newsid;
        if (!isset($aGIDReplacements[$insertdata['gid']]) || trim($insertdata['title'])=='') continue; // Skip questions with invalid group id
        $insertdata['gid']=$aGIDReplacements[$insertdata['gid']];
        $oldqid=$insertdata['qid']; unset($insertdata['qid']); // save the old qid

        // now translate any links
        $insertdata['title']=translink('survey', $oldsid, $newsid, $insertdata['title']);
        $insertdata['question']=translink('survey', $oldsid, $newsid, $insertdata['question']);
        $insertdata['help']=translink('survey', $oldsid, $newsid, $insertdata['help']);
        // Insert the new question    
        if (isset($aQIDReplacements[$oldqid]))
        {
           $insertdata['qid']=$aQIDReplacements[$oldqid];
           db_switchIDInsert('questions',true);
        }   
        $query=$connect->GetInsertSQL($tablename,$insertdata); 
        $result = $connect->Execute($query) or safe_die ($clang->gT("Error").": Failed to insert data<br />{$query}<br />\n".$connect->ErrorMsg());
        if (!isset($aQIDReplacements[$oldqid]))
        {
            $newqid=$connect->Insert_ID($tablename,"qid"); // save this for later
            $aQIDReplacements[$oldqid]=$newqid; // add old and new qid to the mapping array
            $results['questions']++;
        }
        else
        {
           db_switchIDInsert('questions',false);
        }
    }

    // Import subquestions --------------------------------------------------------------
    if (isset($xml->subquestions))
    {
            
        foreach ($xml->subquestions->rows->row as $row)
        {
            $insertdata=array(); 
            foreach ($row as $key=>$value)
            {
                $insertdata[(string)$key]=(string)$value;
            }
            $insertdata['sid']=$newsid;
            if (!isset($aGIDReplacements[$insertdata['gid']])) continue; // Skip questions with invalid group id
            $insertdata['gid']=$aGIDReplacements[(int)$insertdata['gid']];;
            $oldsqid=(int)$insertdata['qid']; unset($insertdata['qid']); // save the old qid
            $insertdata['parent_qid']=$aQIDReplacements[(int)$insertdata['parent_qid']]; // remap the parent_qid

            // now translate any links
            $insertdata['title']=translink('survey', $oldsid, $newsid, $insertdata['title']);
            $insertdata['question']=translink('survey', $oldsid, $newsid, $insertdata['question']);
            $insertdata['help']=translink('survey', $oldsid, $newsid, $insertdata['help']);
            if (isset($aQIDReplacements[$oldsqid])){
               $insertdata['qid']=$aQIDReplacements[$oldsqid];
               db_switchIDInsert('questions',true);
            }
            
            $query=$connect->GetInsertSQL($tablename,$insertdata); 
            $result = $connect->Execute($query) or safe_die ($clang->gT("Error").": Failed to insert data<br />{$query}<br />\n".$connect->ErrorMsg());
            $newsqid=$connect->Insert_ID($tablename,"qid"); // save this for later
            if (!isset($insertdata['qid']))
            {
                $aQIDReplacements[$oldsqid]=$newsqid; // add old and new qid to the mapping array                
            }
            else
            {
               db_switchIDInsert('questions',false);
            }

            $results['subquestions']++;
        }
    }

    // Import answers --------------------------------------------------------------
    if(isset($xml->answers))
    {
        $tablename=$dbprefix.'answers';
        
        foreach ($xml->answers->rows->row as $row)
        {
           $insertdata=array(); 
            foreach ($row as $key=>$value)
            {
                $insertdata[(string)$key]=(string)$value;
            }
            if (!isset($aQIDReplacements[(int)$insertdata['qid']])) continue; // Skip questions with invalid group id
            
            $insertdata['qid']=$aQIDReplacements[(int)$insertdata['qid']]; // remap the parent_qid

            // now translate any links
            $query=$connect->GetInsertSQL($tablename,$insertdata); 
            $result=$connect->Execute($query) or safe_die ($clang->gT("Error").": Failed to insert data<br />{$query}<br />\n".$connect->ErrorMsg());
            $results['answers']++;
        }            
    }

    // Import questionattributes --------------------------------------------------------------
    if(isset($xml->question_attributes))
    {
        $tablename=$dbprefix.'question_attributes';
        
        foreach ($xml->question_attributes->rows->row as $row)
        {
            $insertdata=array(); 
            foreach ($row as $key=>$value)
            {
                $insertdata[(string)$key]=(string)$value;
            }
            unset($insertdata['qaid']);
            if (!isset($aQIDReplacements[(int)$insertdata['qid']])) continue; // Skip questions with invalid group id
            $insertdata['qid']=$aQIDReplacements[(int)$insertdata['qid']]; // remap the parent_qid

            // now translate any links
            $query=$connect->GetInsertSQL($tablename,$insertdata); 
            $result=$connect->Execute($query) or safe_die ($clang->gT("Error").": Failed to insert data<br />{$query}<br />\n".$connect->ErrorMsg());
            $results['question_attributes']++;
        }        
    }
    
    
    // Import defaultvalues --------------------------------------------------------------
    if(isset($xml->defaultvalues))
    {
        $tablename=$dbprefix.'defaultvalues';
        
        $results['defaultvalues']=0;
        foreach ($xml->defaultvalues->rows->row as $row)
        {
           $insertdata=array(); 
            foreach ($row as $key=>$value)
            {
                $insertdata[(string)$key]=(string)$value;
            }
            $insertdata['qid']=$aQIDReplacements[(int)$insertdata['qid']]; // remap the qid
            $insertdata['sqid']=$aQIDReplacements[(int)$insertdata['sqid']]; // remap the subqeustion id

            // now translate any links
            $query=$connect->GetInsertSQL($tablename,$insertdata); 
            $result=$connect->Execute($query) or safe_die ($clang->gT("Error").": Failed to insert data<br />\$query<br />\n".$connect->ErrorMsg());
            $results['defaultvalues']++;
        }             
    }

    // Import conditions --------------------------------------------------------------
    if(isset($xml->conditions))
    {
        $tablename=$dbprefix.'conditions';
        
        foreach ($xml->conditions->rows->row as $row)
        {
           $insertdata=array(); 
            foreach ($row as $key=>$value)
            {
                $insertdata[(string)$key]=(string)$value;
            }
            // 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[$insertdata['qid']]))
            {
                $insertdata['qid']=$aQIDReplacements[$insertdata['qid']]; // remap the qid
            }
            else continue; // a problem with this answer record -> don't consider
            if (isset($aQIDReplacements[$insertdata['cqid']]))
            {
                $insertdata['cqid']=$aQIDReplacements[$insertdata['cqid']]; // remap the qid
            }
            else continue; // a problem with this answer record -> don't consider

            list($oldcsid, $oldcgid, $oldqidanscode) = explode("X",$insertdata["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($insertdata["cid"]);

            // recreate the cfieldname with the new IDs
            if (preg_match("/^\+/",$oldcsid))
            {
                $newcfieldname = '+'.$newsid . "X" . $newgid . "X" . $insertdata["cqid"] .substr($oldqidanscode,strlen($oldqid));
            }
            else
            {
                $newcfieldname = $newsid . "X" . $newgid . "X" . $insertdata["cqid"] .substr($oldqidanscode,strlen($oldqid));
            }

            $insertdata["cfieldname"] = $newcfieldname;
            if (trim($insertdata["method"])=='')
            {
                $insertdata["method"]='==';
            }            

            // now translate any links
            $query=$connect->GetInsertSQL($tablename,$insertdata); 
            $result=$connect->Execute($query) or safe_die ($clang->gT("Error").": Failed to insert data<br />\$query<br />\n".$connect->ErrorMsg());
            $results['conditions']++;
        }             
    }

    
    $results['newgid']=$newgid;
    $results['labelsets']=0;
    $results['labels']=0;
    return $results;
}
importgroup.php (53,747 bytes)   
Bug heat4
Complete LimeSurvey version number (& build)9459
I will donate to the project if issue is resolvedNo
Browserany
Database type & versionMSSQL SERVER 2005 (mssqlnative)
Server OS (if known)Windows server 2003
Webserver software & version (if known)IIS6
PHP Version5.3.3

Users monitoring this issue

There are no users monitoring this issue.

Activities

user1329

2010-11-14 19:34

  ~13523

Just thought it would be useful to indicate the time allowed for a php script to run in my config. Below is an exceirpt of my php.ini limits + IIS timeout=600 sec

;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;

; Maximum execution time of each script, in seconds
; http://php.net/max-execution-time
; Note: This directive is hardcoded to 0 for the CLI SAPI
max_execution_time = 600

; Maximum amount of time each script may spend parsing request data. It's a good
; idea to limit this time on productions servers in order to eliminate unexpectedly
; long running scripts.
; Note: This directive is hardcoded to -1 for the CLI SAPI
; Default Value: -1 (Unlimited)
; Development Value: 60 (60 seconds)
; Production Value: 60 (60 seconds)
; http://php.net/max-input-time
max_input_time = 60

; Maximum input variable nesting level
; http://php.net/max-input-nesting-level
;max_input_nesting_level = 64

; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = 256M

c_schmitz

c_schmitz

2010-11-15 21:16

administrator   ~13529

The problem is the export, not the import.
Please use attached file and export again.
Let us know if the import is fine now.

user1329

2010-11-16 10:15

  ~13536

Thanks for the first patch. It however still does not work when re-importing. The message I get is "This is not a valid LimeSurvey survey structure XML file."

1- I ran your original patch and got a mssql error message in the lss file. I changed line 122 of the export_structure_xml.php to
if ($connect->databaseType == 'odbc_mssql' || $connect->databaseType == 'odbtp' || $connect->databaseType == 'mssql_n' || $connect->databaseType == 'mssqlnative')

(I'm indeed using the mssqlnative driver.)

2- I retested with the change and got the attached lss file called lime_survey_95278_2.lss

3- Re-importing still gives a "This is not a valid LimeSurvey survey structure XML file."

c_schmitz

c_schmitz

2010-11-16 18:10

administrator   ~13537

New file attached. Please test.

user1329

2010-11-17 11:53

  ~13547

Excellent, it now works, many thanks! I have attached the produced lss file for your reference.

-> I've noticed that the same issue exists with LSG files (i.e. exporting a group also gives similar issues) : I have attached the lsg file of the "questionnaire" group extracted from the exact same survey. You'll see that the file is 2.5Mb while the survey file is 458kb.
Do you prefer that I report it as another issue or do we continue in this one?

c_schmitz

c_schmitz

2010-11-18 02:26

administrator   ~13550

Last edited: 2010-11-18 02:27

Thank you. I will have a look at that, too. It is basically the same issue so we can continue here.

c_schmitz

c_schmitz

2010-11-18 03:07

administrator   ~13553

Added two files for exporting question groups and questions. Please test and let me know.

user1329

2010-11-18 12:29

  ~13554


GROUP LSG FILE

I noticed I cannot really test the re-import of an exported lsg file with the patched files attached because I get the following error SQL messages when trying to import the exported group:

Error: Failed to insert data
INSERT INTO lime_groups ( SID, GROUP_NAME, GROUP_ORDER, DESCRIPTION, LANGUAGE ) VALUES ( 11577, 'Questionnaire', 1, '', 'de' )
SQLState: 42000 Error Code: 545 Message: [Microsoft][SQL Server Native Client 10.0][SQL Server]Explicit value must be specified for identity column in table 'lime_groups' either when IDENTITY_INSERT is set to ON or when a replication user is inserting into a NOT FOR REPLICATION identity column.

Error: Failed to insert data
INSERT INTO lime_questions ( QID, SID, GID, TYPE, TITLE, QUESTION, PREG, HELP, OTHER, MANDATORY, QUESTION_ORDER, LANGUAGE, PARENT_QID, SCALE_ID, SAME_DEFAULT ) VALUES ( 1956, 11577, 86, 'T', 'S', 'Soap', '', '', 'N', ' ', 5, 'en', 1932, 0, 0 )
SQLState: 23000 Error Code: 544 Message: [Microsoft][SQL Server Native Client 10.0][SQL Server]Cannot insert explicit value for identity column in table 'lime_questions' when IDENTITY_INSERT is set to OFF.

I have nevertheless included the newly exported lsg file as an attachment.


QUESTION LSQ FILE

When re-importing the LSQ , I obtain the message "This is not a valid LimeSurvey question structure XML file."
I have attached the lsq file as well.

c_schmitz

c_schmitz

2010-11-18 23:48

administrator   ~13557

Thank you. Should be fine now.
Fixed in rev. 9506

c_schmitz

c_schmitz

2010-12-07 14:14

administrator   ~13720

Released in latest 1.90+ version.

Issue History

Date Modified Username Field Change
2010-11-14 19:06 user1329 New Issue
2010-11-14 19:06 user1329 File Added: limesurvey_survey_95278.lss
2010-11-14 19:34 user1329 Note Added: 13523
2010-11-15 21:04 c_schmitz Assigned To => c_schmitz
2010-11-15 21:04 c_schmitz Status new => assigned
2010-11-15 21:16 c_schmitz Note Added: 13529
2010-11-15 21:16 c_schmitz Status assigned => feedback
2010-11-15 21:17 c_schmitz File Added: export_structure_xml.php
2010-11-15 21:19 c_schmitz File Deleted: export_structure_xml.php
2010-11-15 21:19 c_schmitz File Added: export_structure_xml.php
2010-11-16 10:15 user1329 Note Added: 13536
2010-11-16 10:15 user1329 Status feedback => assigned
2010-11-16 10:15 user1329 File Added: limesurvey_survey_95278_2.lss
2010-11-16 18:10 c_schmitz File Deleted: export_structure_xml.php
2010-11-16 18:10 c_schmitz File Added: export_structure_xml.php
2010-11-16 18:10 c_schmitz Note Added: 13537
2010-11-16 18:15 c_schmitz Status assigned => feedback
2010-11-16 20:25 c_schmitz File Deleted: limesurvey_survey_95278.lss
2010-11-17 11:53 user1329 Note Added: 13547
2010-11-17 11:53 user1329 Status feedback => assigned
2010-11-17 11:53 user1329 File Added: limesurvey_survey_95278_3.lss
2010-11-17 11:53 user1329 File Added: limesurvey_group_338.lsg
2010-11-18 02:26 c_schmitz Note Added: 13550
2010-11-18 02:27 c_schmitz Note Edited: 13550
2010-11-18 03:06 c_schmitz File Added: dumpgroup.php
2010-11-18 03:06 c_schmitz File Added: dumpquestion.php
2010-11-18 03:07 c_schmitz File Deleted: limesurvey_group_338.lsg
2010-11-18 03:07 c_schmitz File Deleted: limesurvey_survey_95278_2.lss
2010-11-18 03:07 c_schmitz File Deleted: limesurvey_survey_95278_3.lss
2010-11-18 03:07 c_schmitz Note Added: 13553
2010-11-18 03:07 c_schmitz Status assigned => feedback
2010-11-18 12:29 user1329 Note Added: 13554
2010-11-18 12:29 user1329 Status feedback => assigned
2010-11-18 12:29 user1329 File Added: limesurvey_question_7061.lsq
2010-11-18 12:29 user1329 File Added: limesurvey_group_338.lsg
2010-11-18 23:46 c_schmitz File Deleted: dumpgroup.php
2010-11-18 23:46 c_schmitz File Deleted: dumpquestion.php
2010-11-18 23:47 c_schmitz File Added: dumpquestion.php
2010-11-18 23:47 c_schmitz File Added: importgroup.php
2010-11-18 23:48 c_schmitz Note Added: 13557
2010-11-18 23:48 c_schmitz Status assigned => resolved
2010-11-18 23:48 c_schmitz Resolution open => fixed
2010-12-07 14:14 c_schmitz Note Added: 13720
2010-12-07 14:14 c_schmitz Status resolved => closed