/** * This function imports a LimeSurvey .lss survey XML file * * @param mixed $sFullFilePath The full filepath of the uploaded file */ function XMLImportSurvey($sFullFilePath, $sXMLdata = NULL, $sNewSurveyName = NULL, $iDesiredSurveyId = NULL, $bTranslateInsertansTags = true, $bConvertInvalidQuestionCodes = true) { Yii::app()->loadHelper('database'); $aGIDReplacements = array(); if ($sXMLdata == NULL) { $sXMLdata = file_get_contents($sFullFilePath); } $xml = @simplexml_load_string($sXMLdata, 'SimpleXMLElement', LIBXML_NONET); if (!$xml || $xml->LimeSurveyDocType != 'Survey') { $results['error'] = gT("This is not a valid LimeSurvey survey structure XML file."); return $results; } $iDBVersion = (int) $xml->DBVersion; $aQIDReplacements = array(); $aQuestionCodeReplacements = array(); $aQuotaReplacements = array(); $results['defaultvalues'] = 0; $results['answers'] = 0; $results['surveys'] = 0; $results['questions'] = 0; $results['subquestions'] = 0; $results['question_attributes'] = 0; $results['groups'] = 0; $results['assessments'] = 0; $results['quota'] = 0; $results['quotals'] = 0; $results['quotamembers'] = 0; $results['survey_url_parameters'] = 0; $results['importwarnings'] = array(); $aLanguagesSupported = array(); foreach ($xml->languages->language as $language) { $aLanguagesSupported[] = (string) $language; } $results['languages'] = count($aLanguagesSupported); // Import surveys table ==================================================== foreach ($xml->surveys->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } $iOldSID = $results['oldsid'] = $insertdata['sid']; if ($iDesiredSurveyId != NULL) { $insertdata['wishSID'] = GetNewSurveyID($iDesiredSurveyId); } else { $insertdata['wishSID'] = $iOldSID; } if ($iDBVersion < 145) { if (isset($insertdata['private'])) { $insertdata['anonymized'] = $insertdata['private']; } unset($insertdata['private']); unset($insertdata['notification']); } //Make sure it is not set active $insertdata['active'] = 'N'; //Set current user to be the owner $insertdata['owner_id'] = Yii::app()->session['loginID']; if (isset($insertdata['bouncetime']) && $insertdata['bouncetime'] == '') { $insertdata['bouncetime'] = NULL; } if (isset($insertdata['showXquestions'])) { $insertdata['showxquestions'] = $insertdata['showXquestions']; unset($insertdata['showXquestions']); } if (isset($insertdata['googleAnalyticsStyle'])) { $insertdata['googleanalyticsstyle'] = $insertdata['googleAnalyticsStyle']; unset($insertdata['googleAnalyticsStyle']); } if (isset($insertdata['googleAnalyticsAPIKey'])) { $insertdata['googleanalyticsapikey'] = $insertdata['googleAnalyticsAPIKey']; unset($insertdata['googleAnalyticsAPIKey']); } if (isset($insertdata['allowjumps'])) { $insertdata['questionindex'] = $insertdata['allowjumps'] == "Y" ? 1 : 0; unset($insertdata['allowjumps']); } /* Remove unknow column */ $aSurveyModelsColumns = Survey::model()->attributes; $aSurveyModelsColumns['wishSID'] = null; // To force a sid surely $aBadData = array_diff_key($insertdata, $aSurveyModelsColumns); $insertdata = array_intersect_key($insertdata, $aSurveyModelsColumns); // Fill a optionnal array of error foreach ($aBadData as $key => $value) { $results['importwarnings'][] = sprintf(gT("This survey setting has not been imported: %s => %s"), $key, $value); } $iNewSID = $results['newsid'] = Survey::model()->insertNewSurvey($insertdata) or safeDie(gT("Error") . ": Failed to insert data [1]<br />"); $results['surveys']++; } // Import survey languagesettings table =================================================================================== foreach ($xml->surveys_languagesettings->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } if (!in_array($insertdata['surveyls_language'], $aLanguagesSupported)) { continue; } // Assign new survey ID $insertdata['surveyls_survey_id'] = $iNewSID; // Assign new survey name (if a copy) if ($sNewSurveyName != NULL) { $insertdata['surveyls_title'] = $sNewSurveyName; } if ($bTranslateInsertansTags) { $insertdata['surveyls_title'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_title']); if (isset($insertdata['surveyls_description'])) { $insertdata['surveyls_description'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_description']); } if (isset($insertdata['surveyls_welcometext'])) { $insertdata['surveyls_welcometext'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_welcometext']); } if (isset($insertdata['surveyls_urldescription'])) { $insertdata['surveyls_urldescription'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_urldescription']); } if (isset($insertdata['surveyls_email_invite'])) { $insertdata['surveyls_email_invite'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_invite']); } if (isset($insertdata['surveyls_email_remind'])) { $insertdata['surveyls_email_remind'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_remind']); } if (isset($insertdata['surveyls_email_register'])) { $insertdata['surveyls_email_register'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_register']); } if (isset($insertdata['surveyls_email_confirm'])) { $insertdata['surveyls_email_confirm'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['surveyls_email_confirm']); } } if (isset($insertdata['surveyls_attributecaptions']) && substr($insertdata['surveyls_attributecaptions'], 0, 1) != '{') { unset($insertdata['surveyls_attributecaptions']); } $result = SurveyLanguageSetting::model()->insertNewSurvey($insertdata) or safeDie(gT("Error") . ": Failed to insert data [2]<br />"); } // Import groups table =================================================================================== if (isset($xml->groups->rows->row)) { foreach ($xml->groups->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } if (!in_array($insertdata['language'], $aLanguagesSupported)) { continue; } $iOldSID = $insertdata['sid']; $insertdata['sid'] = $iNewSID; $oldgid = $insertdata['gid']; unset($insertdata['gid']); // save the old qid // now translate any links if ($bTranslateInsertansTags) { $insertdata['group_name'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['group_name']); $insertdata['description'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['description']); } // Insert the new group if (isset($aGIDReplacements[$oldgid])) { switchMSSQLIdentityInsert('groups', true); $insertdata['gid'] = $aGIDReplacements[$oldgid]; } $newgid = QuestionGroup::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data [3]<br />"); $results['groups']++; if (!isset($aGIDReplacements[$oldgid])) { $aGIDReplacements[$oldgid] = $newgid; // add old and new qid to the mapping array } else { switchMSSQLIdentityInsert('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) if (isset($xml->questions)) { foreach ($xml->questions->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } if (!in_array($insertdata['language'], $aLanguagesSupported) || $insertdata['gid'] == 0) { continue; } $iOldSID = $insertdata['sid']; $insertdata['sid'] = $iNewSID; $insertdata['gid'] = $aGIDReplacements[$insertdata['gid']]; $oldqid = $insertdata['qid']; unset($insertdata['qid']); // save the old qid // now translate any links if ($bTranslateInsertansTags) { $insertdata['question'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); $insertdata['help'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['help']); } // Insert the new question if (isset($aQIDReplacements[$oldqid])) { $insertdata['qid'] = $aQIDReplacements[$oldqid]; switchMSSQLIdentityInsert('questions', true); } if ($insertdata) { XSSFilterArray($insertdata); } if (!$bConvertInvalidQuestionCodes) { $sScenario = 'archiveimport'; } else { $sScenario = 'import'; } $oQuestion = new Question($sScenario); $oQuestion->setAttributes($insertdata, false); // Try to fix question title for valid question code enforcement if (!$oQuestion->validate(array('title'))) { $sOldTitle = $oQuestion->title; $sNewTitle = preg_replace("/[^A-Za-z0-9]/", '', $sOldTitle); if (is_numeric(substr($sNewTitle, 0, 1))) { $sNewTitle = 'q' . $sNewTitle; } $oQuestion->title = $sNewTitle; } $attempts = 0; // Try to fix question title for unique question code enforcement while (!$oQuestion->validate(array('title'))) { if (!isset($index)) { $index = 0; $rand = mt_rand(0, 1024); } else { $index++; } $sNewTitle = 'r' . $rand . 'q' . $index; $oQuestion->title = $sNewTitle; $attempts++; if ($attempts > 10) { safeDie(gT("Error") . ": Failed to resolve question code problems after 10 attempts.<br />"); } } if (!$oQuestion->save()) { // safeDie(gT("Error while saving: "). print_r($oQuestion->errors, true)); // // In PHP 5.2.10 a bug is triggered that resets the foreach loop when inserting a record // Problem is that it is the default PHP version on Ubuntu 12.04 LTS (which is currently very common in use) // For this reason we ignore insertion errors (because it is most likely a duplicate) // and continue with the next one continue; } // Set a warning if question title was updated if (isset($sNewTitle)) { $results['importwarnings'][] = sprintf(gT("Question code %s was updated to %s."), $sOldTitle, $sNewTitle); $aQuestionCodeReplacements[$sOldTitle] = $sNewTitle; unset($sNewTitle); unset($sOldTitle); } $newqid = $oQuestion->qid; if (!isset($aQIDReplacements[$oldqid])) { $aQIDReplacements[$oldqid] = $newqid; $results['questions']++; } else { switchMSSQLIdentityInsert('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; } if (!in_array($insertdata['language'], $aLanguagesSupported) || $insertdata['gid'] == 0) { continue; } if (!isset($insertdata['mandatory']) || trim($insertdata['mandatory']) == '') { $insertdata['mandatory'] = 'N'; } $insertdata['sid'] = $iNewSID; $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 if ($bTranslateInsertansTags) { $insertdata['question'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['question']); if (isset($insertdata['help'])) { $insertdata['help'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['help']); } } if (isset($aQIDReplacements[$oldsqid])) { $insertdata['qid'] = $aQIDReplacements[$oldsqid]; switchMSSQLIdentityInsert('questions', true); } if ($insertdata) { XSSFilterArray($insertdata); } if (!$bConvertInvalidQuestionCodes) { $sScenario = 'archiveimport'; } else { $sScenario = 'import'; } $question = new Question($sScenario); $question->setAttributes($insertdata, false); // Try to fix question title for valid question code enforcement if (!$question->validate(array('title'))) { $sOldTitle = $question->title; $sNewTitle = preg_replace("/[^A-Za-z0-9]/", '', $sOldTitle); if (is_numeric(substr($sNewTitle, 0, 1))) { $sNewTitle = 'sq' . $sNewTitle; } $question->title = $sNewTitle; } $attempts = 0; // Try to fix question title for unique question code enforcement while (!$question->validate(array('title'))) { if (!isset($index)) { $index = 0; $rand = mt_rand(0, 1024); } else { $index++; } $sNewTitle = 'r' . $rand . 'sq' . $index; $question->title = $sNewTitle; $attempts++; if ($attempts > 10) { safeDie(gT("Error") . ": Failed to resolve question code problems after 10 attempts.<br />"); } } if (!$question->save()) { // safeDie(gT("Error while saving: "). print_r($question->errors, true)); // // In PHP 5.2.10 a bug is triggered that resets the foreach loop when inserting a record // Problem is that it is the default PHP version on Ubuntu 12.04 LTS (which is currently very common in use) // For this reason we ignore insertion errors (because it is most likely a duplicate) // and continue with the next one continue; } // Set a warning if question title was updated if (isset($sNewTitle)) { $results['importwarnings'][] = sprintf(gT("Title of subquestion %s was updated to %s."), $sOldTitle, $sNewTitle); // Maybe add the question title ? $aQuestionCodeReplacements[$sOldTitle] = $sNewTitle; unset($sNewTitle); unset($sOldTitle); } $newsqid = $question->qid; if (!isset($insertdata['qid'])) { $aQIDReplacements[$oldsqid] = $newsqid; // add old and new qid to the mapping array } else { switchMSSQLIdentityInsert('questions', false); } $results['subquestions']++; } } // Import answers ------------------------------------------------------------ if (isset($xml->answers)) { foreach ($xml->answers->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } if (!in_array($insertdata['language'], $aLanguagesSupported) || !isset($aQIDReplacements[(int) $insertdata['qid']])) { continue; } $insertdata['qid'] = $aQIDReplacements[(int) $insertdata['qid']]; // remap the parent_qid // now translate any links if ($bTranslateInsertansTags) { $insertdata['answer'] = translateLinks('survey', $iOldSID, $iNewSID, $insertdata['answer']); } if ($insertdata) { XSSFilterArray($insertdata); } if (Answer::model()->insertRecords($insertdata)) { $results['answers']++; } } } // Import questionattributes ------------------------------------------------- if (isset($xml->question_attributes)) { $aAllAttributes = \ls\helpers\questionHelper::getAttributesDefinitions(); foreach ($xml->question_attributes->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } // take care of renaming of date min/max adv. attributes fields if ($iDBVersion < 170) { if (isset($insertdata['attribute'])) { if ($insertdata['attribute'] == 'dropdown_dates_year_max') { $insertdata['attribute'] = 'date_max'; } if ($insertdata['attribute'] == 'dropdown_dates_year_min') { $insertdata['attribute'] = 'date_min'; } } } unset($insertdata['qaid']); if (!isset($aQIDReplacements[(int) $insertdata['qid']])) { continue; } $insertdata['qid'] = $aQIDReplacements[(int) $insertdata['qid']]; // remap the qid if ($iDBVersion < 156 && isset($aAllAttributes[$insertdata['attribute']]['i18n']) && $aAllAttributes[$insertdata['attribute']]['i18n']) { foreach ($aLanguagesSupported as $sLanguage) { $insertdata['language'] = $sLanguage; if ($insertdata) { XSSFilterArray($insertdata); } $result = QuestionAttribute::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data[7]<br />"); } } else { $result = QuestionAttribute::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data[8]<br />"); } $results['question_attributes']++; } } // Import defaultvalues ------------------------------------------------------ if (isset($xml->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 if (isset($aQIDReplacements[(int) $insertdata['sqid']])) { $insertdata['sqid'] = $aQIDReplacements[(int) $insertdata['sqid']]; } // remap the subquestion id if ($insertdata) { XSSFilterArray($insertdata); } // now translate any links $result = DefaultValue::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data[9]<br />"); $results['defaultvalues']++; } } $aOldNewFieldmap = reverseTranslateFieldNames($iOldSID, $iNewSID, $aGIDReplacements, $aQIDReplacements); // Import conditions --------------------------------------------------------- if (isset($xml->conditions)) { $results['conditions'] = 0; 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 ($insertdata['cqid'] != 0) { if (isset($aQIDReplacements[$insertdata['cqid']])) { $oldcqid = $insertdata['cqid']; //Save for cfield transformation $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); // replace the gid for the new one in the cfieldname(if there is no new gid in the $aGIDReplacements array it means that this condition is orphan -> error, skip this record) if (!isset($aGIDReplacements[$oldcgid])) { continue; } } unset($insertdata["cid"]); // recreate the cfieldname with the new IDs if ($insertdata['cqid'] != 0) { if (preg_match("/^\\+/", $oldcsid)) { $newcfieldname = '+' . $iNewSID . "X" . $aGIDReplacements[$oldcgid] . "X" . $insertdata["cqid"] . substr($oldqidanscode, strlen($oldcqid)); } else { $newcfieldname = $iNewSID . "X" . $aGIDReplacements[$oldcgid] . "X" . $insertdata["cqid"] . substr($oldqidanscode, strlen($oldcqid)); } } else { // The cfieldname is a not a previous question cfield but a {XXXX} replacement field $newcfieldname = $insertdata["cfieldname"]; } $insertdata["cfieldname"] = $newcfieldname; if (trim($insertdata["method"]) == '') { $insertdata["method"] = '=='; } // Now process the value and replace @sgqa@ codes if (preg_match("/^@(.*)@\$/", $insertdata["value"], $cfieldnameInCondValue)) { if (isset($aOldNewFieldmap[$cfieldnameInCondValue[1]])) { $newvalue = '@' . $aOldNewFieldmap[$cfieldnameInCondValue[1]] . '@'; $insertdata["value"] = $newvalue; } } // now translate any links $result = Condition::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data[10]<br />"); $results['conditions']++; } } // TMSW Condition->Relevance: Call LEM->ConvertConditionsToRelevance // Import assessments -------------------------------------------------------- if (isset($xml->assessments)) { foreach ($xml->assessments->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } if ($insertdata['gid'] > 0) { $insertdata['gid'] = $aGIDReplacements[(int) $insertdata['gid']]; // remap the qid } $insertdata['sid'] = $iNewSID; // remap the survey id unset($insertdata['id']); // now translate any links $result = Assessment::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data[11]<br />"); $results['assessments']++; } } // Import quota -------------------------------------------------------------- if (isset($xml->quota)) { foreach ($xml->quota->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } $insertdata['sid'] = $iNewSID; // remap the survey id $oldid = $insertdata['id']; unset($insertdata['id']); // now translate any links $result = Quota::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data[12]<br />"); $aQuotaReplacements[$oldid] = getLastInsertID('{{quota}}'); $results['quota']++; } } // Import quota_members ------------------------------------------------------ if (isset($xml->quota_members)) { foreach ($xml->quota_members->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } $insertdata['sid'] = $iNewSID; // remap the survey id $insertdata['qid'] = $aQIDReplacements[(int) $insertdata['qid']]; // remap the qid $insertdata['quota_id'] = $aQuotaReplacements[(int) $insertdata['quota_id']]; // remap the qid unset($insertdata['id']); // now translate any links $result = QuotaMember::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data[13]<br />"); $results['quotamembers']++; } } // Import quota_languagesettings---------------------------------------------- if (isset($xml->quota_languagesettings)) { foreach ($xml->quota_languagesettings->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } $insertdata['quotals_quota_id'] = $aQuotaReplacements[(int) $insertdata['quotals_quota_id']]; // remap the qid unset($insertdata['quotals_id']); $result = QuotaLanguageSetting::model()->insertRecords($insertdata) or safeDie(gT("Error") . ": Failed to insert data<br />"); $results['quotals']++; } } // Import survey_url_parameters ---------------------------------------------- if (isset($xml->survey_url_parameters)) { foreach ($xml->survey_url_parameters->rows->row as $row) { $insertdata = array(); foreach ($row as $key => $value) { $insertdata[(string) $key] = (string) $value; } $insertdata['sid'] = $iNewSID; // remap the survey id if (isset($insertdata['targetsqid']) && $insertdata['targetsqid'] != '') { $insertdata['targetsqid'] = $aQIDReplacements[(int) $insertdata['targetsqid']]; // remap the qid } if (isset($insertdata['targetqid']) && $insertdata['targetqid'] != '') { $insertdata['targetqid'] = $aQIDReplacements[(int) $insertdata['targetqid']]; // remap the qid } unset($insertdata['id']); $result = SurveyURLParameter::model()->insertRecord($insertdata) or safeDie(gT("Error") . ": Failed to insert data[14]<br />"); $results['survey_url_parameters']++; } } // Set survey rights Permission::model()->giveAllSurveyPermissions(Yii::app()->session['loginID'], $iNewSID); $aOldNewFieldmap = reverseTranslateFieldNames($iOldSID, $iNewSID, $aGIDReplacements, $aQIDReplacements); $results['FieldReMap'] = $aOldNewFieldmap; LimeExpressionManager::SetSurveyId($iNewSID); translateInsertansTags($iNewSID, $iOldSID, $aOldNewFieldmap); replaceExpressionCodes($iNewSID, $aQuestionCodeReplacements); if (count($aQuestionCodeReplacements)) { array_unshift($results['importwarnings'], "<span class='warningtitle'>" . gT('Attention: Several question codes were updated. Please check these carefully as the update may not be perfect with customized expressions.') . '</span)>'); } LimeExpressionManager::RevertUpgradeConditionsToRelevance($iNewSID); LimeExpressionManager::UpgradeConditionsToRelevance($iNewSID); return $results; }
/** * TSV survey definition in format readable by TSVSurveyImport * one line each per group, question, sub-question, and answer * does not use SGQA naming at all. * @param type $sid * @return type */ public static function &TSVSurveyExport($sid) { $aBaseFields = array('class', 'type/scale', 'name', 'relevance', 'text', 'help', 'language', 'validation', 'mandatory', 'other', 'default', 'same_default'); // Advanced question attributes : @todo get used question attribute by question in survey ? $aQuestionAttributes = array_keys(\ls\helpers\questionHelper::getAttributesDefinitions()); sort($aQuestionAttributes); $fields = array_merge($aBaseFields, $aQuestionAttributes); $rows = array(); $primarylang = 'en'; $otherlangs = ''; $langs = array(); // Export survey-level information $query = "select * from {{surveys}} where sid = " . $sid; $data = dbExecuteAssoc($query); foreach ($data->readAll() as $r) { foreach ($r as $key => $value) { if ($value != '') { $row['class'] = 'S'; $row['name'] = $key; $row['text'] = $value; $rows[] = $row; } if ($key == 'language') { $primarylang = $value; } if ($key == 'additional_languages') { $otherlangs = $value; } } } $langs = explode(' ', $primarylang . ' ' . $otherlangs); $langs = array_unique($langs); // Export survey language settings $query = "select * from {{surveys_languagesettings}} where surveyls_survey_id = " . $sid; $data = dbExecuteAssoc($query); foreach ($data->readAll() as $r) { $_lang = $r['surveyls_language']; foreach ($r as $key => $value) { if ($value != '' && $key != 'surveyls_language' && $key != 'surveyls_survey_id') { $row['class'] = 'SL'; $row['name'] = $key; $row['text'] = $value; $row['language'] = $_lang; $rows[] = $row; } } } $surveyinfo = getSurveyInfo($sid); $assessments = false; if (isset($surveyinfo['assessments']) && $surveyinfo['assessments'] == 'Y') { $assessments = true; } foreach ($langs as $lang) { if (trim($lang) == '') { continue; } SetSurveyLanguage($sid, $lang); LimeExpressionManager::StartSurvey($sid, 'survey', array('sgqaNaming' => 'N', 'assessments' => $assessments), true); $moveResult = LimeExpressionManager::NavigateForwards(); $LEM =& LimeExpressionManager::singleton(); if (is_null($moveResult) || is_null($LEM->currentQset) || count($LEM->currentQset) == 0) { continue; } $_gseq = -1; foreach ($LEM->currentQset as $q) { $gseq = $q['info']['gseq']; $gid = $q['info']['gid']; $qid = $q['info']['qid']; ////// // SHOW GROUP-LEVEL INFO ////// if ($gseq != $_gseq) { $_gseq = $gseq; $ginfo = $LEM->gseq2info[$gseq]; // if relevance equation is using SGQA coding, convert to qcoding $grelevance = $ginfo['grelevance'] == '' ? 1 : $ginfo['grelevance']; $LEM->em->ProcessBooleanExpression($grelevance, $gseq, 0); // $qseq $grelevance = trim(strip_tags($LEM->em->GetPrettyPrintString())); $gtext = trim($ginfo['description']) == '' ? '' : $ginfo['description']; $row = array(); $row['class'] = 'G'; //create a group code to allow proper importing of multi-lang survey TSVs $row['type/scale'] = 'G' . $gseq; $row['name'] = $ginfo['group_name']; $row['relevance'] = $grelevance; $row['text'] = $gtext; $row['language'] = $lang; $row['random_group'] = $ginfo['randomization_group']; $rows[] = $row; } ////// // SHOW QUESTION-LEVEL INFO ////// $row = array(); $mandatory = $q['info']['mandatory'] == 'Y' ? 'Y' : ''; $type = $q['info']['type']; $sgqas = explode('|', $q['sgqa']); if (count($sgqas) == 1 && !is_null($q['info']['default'])) { $default = $q['info']['default']; } else { $default = ''; } $qtext = $q['info']['qtext'] != '' ? $q['info']['qtext'] : ''; $help = $q['info']['help'] != '' ? $q['info']['help'] : ''; ////// // SHOW QUESTION ATTRIBUTES THAT ARE PROCESSED BY EM ////// if (isset($LEM->qattr[$qid]) && count($LEM->qattr[$qid]) > 0) { foreach ($LEM->qattr[$qid] as $key => $value) { if (is_null($value) || trim($value) == '') { continue; } switch ($key) { default: case 'exclude_all_others': case 'exclude_all_others_auto': case 'hidden': if ($value == false || $value == '0') { $value = NULL; // so can skip this one - just using continue here doesn't work. } break; case 'relevance': $value = NULL; // means an outdate database structure break; } if (is_null($value) || trim($value) == '') { continue; // since continuing from within a switch statement doesn't work } $row[$key] = $value; } } // if relevance equation is using SGQA coding, convert to qcoding $relevanceEqn = $q['info']['relevance'] == '' ? 1 : $q['info']['relevance']; $LEM->em->ProcessBooleanExpression($relevanceEqn, $gseq, $q['info']['qseq']); // $qseq $relevanceEqn = trim(preg_replace("#</(span|a)>#i", "", preg_replace("#<(span|a)[^>]+\\>#i", "", $LEM->em->GetPrettyPrintString()))); // Relevance can not have HTML : only span and a are returned from GetPrettyPrintString $rootVarName = $q['info']['rootVarName']; $preg = ''; if (isset($LEM->q2subqInfo[$q['info']['qid']]['preg'])) { $preg = $LEM->q2subqInfo[$q['info']['qid']]['preg']; if (is_null($preg)) { $preg = ''; } } $row['class'] = 'Q'; $row['type/scale'] = $type; $row['name'] = $rootVarName; $row['relevance'] = $relevanceEqn; $row['text'] = $qtext; $row['help'] = $help; $row['language'] = $lang; $row['validation'] = $preg; $row['mandatory'] = $mandatory; $row['other'] = $q['info']['other']; $row['default'] = $default; $row['same_default'] = 1; // TODO - need this: $q['info']['same_default']; $rows[] = $row; ////// // SHOW ALL SUB-QUESTIONS ////// $sawThis = array(); // array of rowdivids already seen so only show them once foreach ($sgqas as $sgqa) { if ($LEM->knownVars[$sgqa]['qcode'] == $rootVarName) { continue; // so don't show the main question as a sub-question too } $rowdivid = $sgqa; $varName = $LEM->knownVars[$sgqa]['qcode']; // if SQrelevance equation is using SGQA coding, convert to qcoding $SQrelevance = $LEM->knownVars[$sgqa]['SQrelevance'] == '' ? 1 : $LEM->knownVars[$sgqa]['SQrelevance']; $LEM->em->ProcessBooleanExpression($SQrelevance, $gseq, $q['info']['qseq']); $SQrelevance = trim(preg_replace("#</(span|a)>#i", "", preg_replace("#<(span|a)[^>]+\\>#i", "", $LEM->em->GetPrettyPrintString()))); // Relevance can not have HTML : only span and a are returned from GetPrettyPrintString switch ($q['info']['type']) { case '1': if (preg_match('/#1$/', $sgqa)) { $rowdivid = NULL; // so that doesn't show same message for second scale } else { $rowdivid = substr($sgqa, 0, -2); // strip suffix $varName = substr($LEM->knownVars[$sgqa]['qcode'], 0, -2); } break; case 'P': if (preg_match('/comment$/', $sgqa)) { $rowdivid = NULL; } break; case ':': case ';': $_rowdivid = $LEM->knownVars[$sgqa]['rowdivid']; if (isset($sawThis[$qid . '~' . $_rowdivid])) { $rowdivid = NULL; // so don't show again } else { $sawThis[$qid . '~' . $_rowdivid] = true; $rowdivid = $_rowdivid; $sgqa_len = strlen($sid . 'X' . $gid . 'X' . $qid); $varName = $rootVarName . '_' . substr($_rowdivid, $sgqa_len); } break; } if (is_null($rowdivid)) { continue; } $sgqaInfo = $LEM->knownVars[$sgqa]; $subqText = $sgqaInfo['subqtext']; if (isset($sgqaInfo['default'])) { $default = $sgqaInfo['default']; } else { $default = ''; } $row = array(); $row['class'] = 'SQ'; $row['type/scale'] = 0; $row['name'] = substr($varName, strlen($rootVarName) + 1); $row['relevance'] = $SQrelevance; $row['text'] = $subqText; $row['language'] = $lang; $row['default'] = $default; $rows[] = $row; } ////// // SHOW ANSWER OPTIONS FOR ENUMERATED LISTS, AND FOR MULTIFLEXI ////// if (isset($LEM->qans[$qid]) || isset($LEM->multiflexiAnswers[$qid])) { $_scale = -1; if (isset($LEM->multiflexiAnswers[$qid])) { $ansList = $LEM->multiflexiAnswers[$qid]; } else { $ansList = $LEM->qans[$qid]; } foreach ($ansList as $ans => $value) { $ansInfo = explode('~', $ans); $valParts = explode('|', $value); $valInfo[0] = array_shift($valParts); $valInfo[1] = implode('|', $valParts); if ($_scale != $ansInfo[0]) { $_scale = $ansInfo[0]; } $row = array(); if ($type == ':' || $type == ';') { $row['class'] = 'SQ'; } else { $row['class'] = 'A'; } $row['type/scale'] = $_scale; $row['name'] = $ansInfo[1]; $row['relevance'] = $assessments == true ? $valInfo[0] : ''; $row['text'] = $valInfo[1]; $row['language'] = $lang; $rows[] = $row; } } } } // Now generate the array out output data $out = array(); $out[] = $fields; foreach ($rows as $row) { $tsv = array(); foreach ($fields as $field) { $val = isset($row[$field]) ? $row[$field] : ''; $tsv[] = $val; } $out[] = $tsv; } return $out; }