/** * Create the arrays needed by ExpressionManager to process LimeSurvey strings. * The long part of this function should only be called once per page display (e.g. only if $fieldMap changes) * * @param <integer> $surveyid * @param <Boolean> $forceRefresh * @param <Boolean> $anonymized * @param <Boolean> $allOnOnePage - if true (like for survey_format), uses certain optimizations * @return boolean - true if $fieldmap had been re-created, so ExpressionManager variables need to be re-set */ private function setVariableAndTokenMappingsForExpressionManager($surveyid, $forceRefresh = false, $anonymized = false, $allOnOnePage = false) { if (isset($_SESSION['LEMforceRefresh'])) { unset($_SESSION['LEMforceRefresh']); $forceRefresh = true; } else { if (!$forceRefresh && isset($this->knownVars) && !$this->sPreviewMode) { return false; // means that those variables have been cached and no changes needed } } $now = microtime(true); $this->em->SetSurveyMode($this->surveyMode); // TODO - do I need to force refresh, or trust that createFieldMap will cache langauges properly? $fieldmap = createFieldMap($surveyid, $style = 'full', $forceRefresh, false, $_SESSION['LEMlang']); $this->sid = $surveyid; $this->runtimeTimings[] = array(__METHOD__ . '.createFieldMap', microtime(true) - $now); // LimeExpressionManager::ShowStackTrace(); $now = microtime(true); if (!isset($fieldmap)) { return false; // implies an error occurred } $this->knownVars = array(); // mapping of VarName to Value $this->qcode2sgqa = array(); $this->tempVars = array(); $this->qid2code = array(); // List of codes for each question - needed to know which to NULL if a question is irrelevant $this->jsVar2qid = array(); $this->qcode2sgq = array(); $this->alias2varName = array(); $this->varNameAttr = array(); $this->questionId2questionSeq = array(); $this->questionId2groupSeq = array(); $this->questionSeq2relevance = array(); $this->groupId2groupSeq = array(); $this->qid2validationEqn = array(); $this->groupSeqInfo = array(); $this->gseq2relevanceStatus = array(); // Since building array of allowable answers, need to know preset values for certain question types $presets = array(); $presets['G'] = array('M' => $this->gT("Male"), 'F' => $this->gT("Female")); $presets['Y'] = array('Y' => $this->gT("Yes"), 'N' => $this->gT("No")); $presets['C'] = array('Y' => $this->gT("Yes"), 'N' => $this->gT("No"), 'U' => $this->gT("Uncertain")); $presets['E'] = array('I' => $this->gT("Increase"), 'S' => $this->gT("Same"), 'D' => $this->gT("Decrease")); $this->gseq2info = $this->getGroupInfoForEM($surveyid, $_SESSION['LEMlang']); foreach ($this->gseq2info as $aGroupInfo) { $this->groupId2groupSeq[$aGroupInfo['gid']] = $aGroupInfo['group_order']; } $qattr = $this->getQuestionAttributesForEM($surveyid, 0, $_SESSION['LEMlang']); $this->qattr = $qattr; $this->runtimeTimings[] = array(__METHOD__ . ' - question_attributes_model->getQuestionAttributesForEM', microtime(true) - $now); $now = microtime(true); $this->qans = $this->getAnswerSetsForEM($surveyid, NULL, $_SESSION['LEMlang']); $this->runtimeTimings[] = array(__METHOD__ . ' - answers_model->getAnswerSetsForEM', microtime(true) - $now); $now = microtime(true); $q2subqInfo = array(); $this->multiflexiAnswers = array(); foreach ($fieldmap as $fielddata) { if (!isset($fielddata['fieldname']) || !preg_match('#^\\d+X\\d+X\\d+#', $fielddata['fieldname'])) { continue; // not an SGQA value } $sgqa = $fielddata['fieldname']; $type = $fielddata['type']; $mandatory = $fielddata['mandatory']; $fieldNameParts = explode('X', $sgqa); $groupNum = $fieldNameParts[1]; $aid = isset($fielddata['aid']) ? $fielddata['aid'] : ''; $sqid = isset($fielddata['sqid']) ? $fielddata['sqid'] : ''; if ($this->sPreviewMode == 'question') { $fielddata['relevance'] = 1; } if ($this->sPreviewMode == 'group') { $fielddata['grelevance'] = 1; } $questionId = $fieldNameParts[2]; $questionNum = $fielddata['qid']; $relevance = isset($fielddata['relevance']) ? $fielddata['relevance'] : 1; $SQrelevance = isset($fielddata['SQrelevance']) ? $fielddata['SQrelevance'] : 1; $grelevance = isset($fielddata['grelevance']) ? $fielddata['grelevance'] : 1; $hidden = isset($qattr[$questionNum]['hidden']) ? $qattr[$questionNum]['hidden'] == '1' : false; $scale_id = isset($fielddata['scale_id']) ? $fielddata['scale_id'] : '0'; $preg = isset($fielddata['preg']) ? $fielddata['preg'] : NULL; // a perl regular exrpession validation function $defaultValue = isset($fielddata['defaultvalue']) ? $fielddata['defaultvalue'] : NULL; if (trim($preg) == '') { $preg = NULL; } $help = isset($fielddata['help']) ? $fielddata['help'] : ''; $other = isset($fielddata['other']) ? $fielddata['other'] : ''; if (isset($this->questionId2groupSeq[$questionNum])) { $groupSeq = $this->questionId2groupSeq[$questionNum]; } else { $groupSeq = isset($fielddata['groupSeq']) ? $fielddata['groupSeq'] : -1; $this->questionId2groupSeq[$questionNum] = $groupSeq; } if (isset($this->questionId2questionSeq[$questionNum])) { $questionSeq = $this->questionId2questionSeq[$questionNum]; } else { $questionSeq = isset($fielddata['questionSeq']) ? $fielddata['questionSeq'] : -1; $this->questionId2questionSeq[$questionNum] = $questionSeq; } if (!isset($this->groupSeqInfo[$groupSeq])) { $this->groupSeqInfo[$groupSeq] = array('qstart' => $questionSeq, 'qend' => $questionSeq); } else { $this->groupSeqInfo[$groupSeq]['qend'] = $questionSeq; // with each question, update so know ending value } // Create list of codes associated with each question $codeList = isset($this->qid2code[$questionNum]) ? $this->qid2code[$questionNum] : ''; if ($codeList == '') { $codeList = $sgqa; } else { $codeList .= '|' . $sgqa; } $this->qid2code[$questionNum] = $codeList; $readWrite = 'Y'; // Set $ansArray switch ($type) { case '!': //List - dropdown //List - dropdown case 'L': //LIST drop-down/radio-button list //LIST drop-down/radio-button list case 'O': //LIST WITH COMMENT drop-down/radio-button list + textarea //LIST WITH COMMENT drop-down/radio-button list + textarea case '1': //Array (Flexible Labels) dual scale // need scale //Array (Flexible Labels) dual scale // need scale case 'H': //ARRAY (Flexible) - Column Format //ARRAY (Flexible) - Column Format case 'F': //ARRAY (Flexible) - Row Format //ARRAY (Flexible) - Row Format case 'R': //RANKING STYLE $ansArray = isset($this->qans[$questionNum]) ? $this->qans[$questionNum] : NULL; if ($other == 'Y' && ($type == 'L' || $type == '!')) { if (preg_match('/other$/', $sgqa)) { $ansArray = NULL; // since the other variable doesn't need it } else { $_qattr = isset($qattr[$questionNum]) ? $qattr[$questionNum] : array(); if (isset($_qattr['other_replace_text']) && trim($_qattr['other_replace_text']) != '') { $othertext = trim($_qattr['other_replace_text']); } else { $othertext = $this->gT('Other:'); } $ansArray['0~-oth-'] = '0|' . $othertext; } } break; case 'A': //ARRAY (5 POINT CHOICE) radio-buttons //ARRAY (5 POINT CHOICE) radio-buttons case 'B': //ARRAY (10 POINT CHOICE) radio-buttons //ARRAY (10 POINT CHOICE) radio-buttons case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case '5': //5 POINT CHOICE radio-buttons $ansArray = NULL; break; case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case 'K': //MULTIPLE NUMERICAL QUESTION //MULTIPLE NUMERICAL QUESTION case 'Q': //MULTIPLE SHORT TEXT //MULTIPLE SHORT TEXT case ';': //ARRAY (Multi Flexi) Text //ARRAY (Multi Flexi) Text case 'S': //SHORT FREE TEXT //SHORT FREE TEXT case 'T': //LONG FREE TEXT //LONG FREE TEXT case 'U': //HUGE FREE TEXT //HUGE FREE TEXT case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'P': //Multiple choice with comments checkbox + text //Multiple choice with comments checkbox + text case 'D': //DATE //DATE case '*': //Equation //Equation case 'I': //Language Question //Language Question case '|': //File Upload //File Upload case 'X': //BOILERPLATE QUESTION $ansArray = NULL; break; case 'G': //GENDER drop-down list //GENDER drop-down list case 'Y': //YES/NO radio-buttons //YES/NO radio-buttons case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons //ARRAY (YES/UNCERTAIN/NO) radio-buttons case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons $ansArray = $presets[$type]; break; } // set $subqtext text - for display of primary sub-question $subqtext = ''; switch ($type) { default: $subqtext = isset($fielddata['subquestion']) ? $fielddata['subquestion'] : ''; break; case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case ';': //ARRAY (Multi Flexi) Text $subqtext = isset($fielddata['subquestion1']) ? $fielddata['subquestion1'] : ''; $ansList = array(); if (isset($fielddata['answerList'])) { foreach ($fielddata['answerList'] as $ans) { $ansList['1~' . $ans['code']] = $ans['code'] . '|' . $ans['answer']; } $this->multiflexiAnswers[$questionNum] = $ansList; } break; } // Set $varName (question code / questions.title), $rowdivid, $csuffix, $sqsuffix, and $question $rowdivid = NULL; // so that blank for types not needing it. $sqsuffix = ''; switch ($type) { case '!': //List - dropdown //List - dropdown case '5': //5 POINT CHOICE radio-buttons //5 POINT CHOICE radio-buttons case 'D': //DATE //DATE case 'G': //GENDER drop-down list //GENDER drop-down list case 'I': //Language Question //Language Question case 'L': //LIST drop-down/radio-button list //LIST drop-down/radio-button list case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case 'O': //LIST WITH COMMENT drop-down/radio-button list + textarea //LIST WITH COMMENT drop-down/radio-button list + textarea case 'S': //SHORT FREE TEXT //SHORT FREE TEXT case 'T': //LONG FREE TEXT //LONG FREE TEXT case 'U': //HUGE FREE TEXT //HUGE FREE TEXT case 'X': //BOILERPLATE QUESTION //BOILERPLATE QUESTION case 'Y': //YES/NO radio-buttons //YES/NO radio-buttons case '|': //File Upload //File Upload case '*': //Equation $csuffix = ''; $sqsuffix = ''; $varName = $fielddata['title']; if ($fielddata['aid'] != '') { $varName .= '_' . $fielddata['aid']; } $question = $fielddata['question']; break; case '1': //Array (Flexible Labels) dual scale $csuffix = $fielddata['aid'] . '#' . $fielddata['scale_id']; $sqsuffix = '_' . $fielddata['aid']; $varName = $fielddata['title'] . '_' . $fielddata['aid'] . '_' . $fielddata['scale_id']; $question = $fielddata['subquestion'] . '[' . $fielddata['scale'] . ']'; // $question = $fielddata['question'] . ': ' . $fielddata['subquestion'] . '[' . $fielddata['scale'] . ']'; $rowdivid = substr($sgqa, 0, -2); break; case 'A': //ARRAY (5 POINT CHOICE) radio-buttons //ARRAY (5 POINT CHOICE) radio-buttons case 'B': //ARRAY (10 POINT CHOICE) radio-buttons //ARRAY (10 POINT CHOICE) radio-buttons case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons //ARRAY (YES/UNCERTAIN/NO) radio-buttons case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons //ARRAY (Increase/Same/Decrease) radio-buttons case 'F': //ARRAY (Flexible) - Row Format //ARRAY (Flexible) - Row Format case 'H': //ARRAY (Flexible) - Column Format // note does not have javatbd equivalent - so array filters don't work on it //ARRAY (Flexible) - Column Format // note does not have javatbd equivalent - so array filters don't work on it case 'K': //MULTIPLE NUMERICAL QUESTION // note does not have javatbd equivalent - so array filters don't work on it, but need rowdivid to process validations //MULTIPLE NUMERICAL QUESTION // note does not have javatbd equivalent - so array filters don't work on it, but need rowdivid to process validations case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'P': //Multiple choice with comments checkbox + text //Multiple choice with comments checkbox + text case 'Q': //MULTIPLE SHORT TEXT // note does not have javatbd equivalent - so array filters don't work on it //MULTIPLE SHORT TEXT // note does not have javatbd equivalent - so array filters don't work on it case 'R': //RANKING STYLE // note does not have javatbd equivalent - so array filters don't work on it $csuffix = $fielddata['aid']; $varName = $fielddata['title'] . '_' . $fielddata['aid']; $question = $fielddata['subquestion']; // $question = $fielddata['question'] . ': ' . $fielddata['subquestion']; if ($type != 'H') { if ($type == 'P' && preg_match("/comment\$/", $sgqa)) { // $rowdivid = substr($sgqa,0,-7); } else { $sqsuffix = '_' . $fielddata['aid']; $rowdivid = $sgqa; } } break; case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case ';': //ARRAY (Multi Flexi) Text $csuffix = $fielddata['aid']; $sqsuffix = '_' . substr($fielddata['aid'], 0, strpos($fielddata['aid'], '_')); $varName = $fielddata['title'] . '_' . $fielddata['aid']; $question = $fielddata['subquestion1'] . '[' . $fielddata['subquestion2'] . ']'; // $question = $fielddata['question'] . ': ' . $fielddata['subquestion1'] . '[' . $fielddata['subquestion2'] . ']'; $rowdivid = substr($sgqa, 0, strpos($sgqa, '_')); break; } // $onlynum $onlynum = false; // the default switch ($type) { case 'K': //MULTIPLE NUMERICAL QUESTION //MULTIPLE NUMERICAL QUESTION case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case ':': //ARRAY (Multi Flexi) 1 to 10 $onlynum = true; break; case '*': // Equation // Equation case ';': //ARRAY (Multi Flexi) Text //ARRAY (Multi Flexi) Text case 'Q': //MULTIPLE SHORT TEXT //MULTIPLE SHORT TEXT case 'S': //SHORT FREE TEXT if (isset($qattr[$questionNum]['numbers_only']) && $qattr[$questionNum]['numbers_only'] == '1') { $onlynum = true; } break; case 'L': //LIST drop-down/radio-button list //LIST drop-down/radio-button list case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'P': //Multiple choice with comments checkbox + text if (isset($qattr[$questionNum]['other_numbers_only']) && $qattr[$questionNum]['other_numbers_only'] == '1' && preg_match('/other$/', $sgqa)) { $onlynum = true; } break; default: break; } // Set $jsVarName_on (for on-page variables - e.g. answerSGQA) and $jsVarName (for off-page variables; the primary name - e.g. javaSGQA) switch ($type) { case 'R': //RANKING STYLE $jsVarName_on = 'answer' . $sgqa; $jsVarName = 'java' . $sgqa; break; case 'D': //DATE //DATE case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case 'S': //SHORT FREE TEXT //SHORT FREE TEXT case 'T': //LONG FREE TEXT //LONG FREE TEXT case 'U': //HUGE FREE TEXT //HUGE FREE TEXT case 'Q': //MULTIPLE SHORT TEXT //MULTIPLE SHORT TEXT case 'K': //MULTIPLE NUMERICAL QUESTION //MULTIPLE NUMERICAL QUESTION case 'X': //BOILERPLATE QUESTION $jsVarName_on = 'answer' . $sgqa; $jsVarName = 'java' . $sgqa; break; case '!': //List - dropdown if (preg_match("/other\$/", $sgqa)) { $jsVarName = 'java' . $sgqa; $jsVarName_on = 'othertext' . substr($sgqa, 0, -5); } else { $jsVarName = 'java' . $sgqa; $jsVarName_on = $jsVarName; } break; case 'L': //LIST drop-down/radio-button list if (preg_match("/other\$/", $sgqa)) { $jsVarName = 'java' . $sgqa; $jsVarName_on = 'answer' . $sgqa . "text"; } else { $jsVarName = 'java' . $sgqa; $jsVarName_on = $jsVarName; } break; case '5': //5 POINT CHOICE radio-buttons //5 POINT CHOICE radio-buttons case 'G': //GENDER drop-down list //GENDER drop-down list case 'I': //Language Question //Language Question case 'Y': //YES/NO radio-buttons //YES/NO radio-buttons case '*': //Equation //Equation case 'A': //ARRAY (5 POINT CHOICE) radio-buttons //ARRAY (5 POINT CHOICE) radio-buttons case 'B': //ARRAY (10 POINT CHOICE) radio-buttons //ARRAY (10 POINT CHOICE) radio-buttons case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons //ARRAY (YES/UNCERTAIN/NO) radio-buttons case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons //ARRAY (Increase/Same/Decrease) radio-buttons case 'F': //ARRAY (Flexible) - Row Format //ARRAY (Flexible) - Row Format case 'H': //ARRAY (Flexible) - Column Format //ARRAY (Flexible) - Column Format case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'O': //LIST WITH COMMENT drop-down/radio-button list + textarea if ($type == 'O' && preg_match('/_comment$/', $varName)) { $jsVarName_on = 'answer' . $sgqa; } else { $jsVarName_on = 'java' . $sgqa; } $jsVarName = 'java' . $sgqa; break; case '1': //Array (Flexible Labels) dual scale $jsVarName = 'java' . str_replace('#', '_', $sgqa); $jsVarName_on = $jsVarName; break; case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case ';': //ARRAY (Multi Flexi) Text $jsVarName = 'java' . $sgqa; $jsVarName_on = 'answer' . $sgqa; break; case '|': //File Upload $jsVarName = $sgqa; $jsVarName_on = $jsVarName; break; case 'P': //Multiple choice with comments checkbox + text if (preg_match("/(other|comment)\$/", $sgqa)) { $jsVarName_on = 'answer' . $sgqa; // is this true for survey.php and not for group.php? $jsVarName = 'java' . $sgqa; } else { $jsVarName = 'java' . $sgqa; $jsVarName_on = $jsVarName; } break; } // Hidden question are never on same page (except for equation) if ($hidden && $type != "*") { $jsVarName_on = ''; } if (!is_null($rowdivid) || $type == 'L' || $type == 'N' || $type == '!' || $type == 'O' || !is_null($preg) || $type == 'S' || $type == 'D' || $type == 'T' || $type == 'U' || $type == '|') { if (!isset($q2subqInfo[$questionNum])) { $q2subqInfo[$questionNum] = array('qid' => $questionNum, 'qseq' => $questionSeq, 'gseq' => $groupSeq, 'sgqa' => $surveyid . 'X' . $groupNum . 'X' . $questionNum, 'mandatory' => $mandatory, 'varName' => $varName, 'type' => $type, 'fieldname' => $sgqa, 'preg' => $preg, 'rootVarName' => $fielddata['title']); } if (!isset($q2subqInfo[$questionNum]['subqs'])) { $q2subqInfo[$questionNum]['subqs'] = array(); } switch ($type) { case 'L': // What using sq: it's only on question + one other if other is set. This don't set the other subq here. // What using sq: it's only on question + one other if other is set. This don't set the other subq here. case '!': if (!is_null($ansArray)) { foreach (array_keys($ansArray) as $key) { $parts = explode('~', $key); if ($parts[1] == '-oth-') { $parts[1] = 'other'; } $q2subqInfo[$questionNum]['subqs'][] = array('rowdivid' => $surveyid . 'X' . $groupNum . 'X' . $questionNum . $parts[1], 'varName' => $varName, 'sqsuffix' => '_' . $parts[1]); } } break; case 'O': if (strlen($varName) > 8 && substr_compare($varName, '_comment', -8) === 0) { $q2subqInfo[$questionNum]['subqs'][] = array('varName' => $varName, 'rowdivid' => $surveyid . 'X' . $groupNum . 'X' . $questionNum . 'comment', 'jsVarName' => $jsVarName, 'jsVarName_on' => $jsVarName_on, 'sqsuffix' => '_comment'); } else { $q2subqInfo[$questionNum]['subqs'][] = array('varName' => $varName, 'rowdivid' => $surveyid . 'X' . $groupNum . 'X' . $questionNum, 'jsVarName' => $jsVarName, 'jsVarName_on' => $jsVarName_on); } break; case 'N': case 'S': case 'D': case 'T': case 'U': $q2subqInfo[$questionNum]['subqs'][] = array('varName' => $varName, 'rowdivid' => $surveyid . 'X' . $groupNum . 'X' . $questionNum, 'jsVarName' => 'java' . $surveyid . 'X' . $groupNum . 'X' . $questionNum, 'jsVarName_on' => $jsVarName_on); break; default: $q2subqInfo[$questionNum]['subqs'][] = array('rowdivid' => $rowdivid, 'varName' => $varName, 'jsVarName_on' => $jsVarName_on, 'jsVarName' => $jsVarName, 'csuffix' => $csuffix, 'sqsuffix' => $sqsuffix); break; } } $ansList = ''; if (isset($ansArray) && !is_null($ansArray)) { $answers = array(); foreach ($ansArray as $key => $value) { $answers[] = "'" . $key . "':'" . htmlspecialchars(preg_replace('/[[:space:]]/', ' ', $value), ENT_QUOTES) . "'"; } $ansList = ",'answers':{ " . implode(",", $answers) . "}"; } // Set mappings of variable names to needed attributes $varInfo_Code = array('jsName_on' => $jsVarName_on, 'jsName' => $jsVarName, 'readWrite' => $readWrite, 'hidden' => $hidden, 'question' => $question, 'qid' => $questionNum, 'gid' => $groupNum, 'grelevance' => $grelevance, 'relevance' => $relevance, 'SQrelevance' => $SQrelevance, 'qcode' => $varName, 'qseq' => $questionSeq, 'gseq' => $groupSeq, 'type' => $type, 'sgqa' => $sgqa, 'ansList' => $ansList, 'ansArray' => $ansArray, 'scale_id' => $scale_id, 'default' => $defaultValue, 'rootVarName' => $fielddata['title'], 'subqtext' => $subqtext, 'rowdivid' => is_null($rowdivid) ? '' : $rowdivid, 'onlynum' => $onlynum); $this->questionSeq2relevance[$questionSeq] = array('relevance' => $relevance, 'grelevance' => $grelevance, 'qid' => $questionNum, 'qseq' => $questionSeq, 'gseq' => $groupSeq, 'jsResultVar_on' => $jsVarName_on, 'jsResultVar' => $jsVarName, 'type' => $type, 'hidden' => $hidden, 'gid' => $groupNum, 'mandatory' => $mandatory, 'eqn' => '', 'help' => $help, 'qtext' => $fielddata['question'], 'code' => $varName, 'other' => $other, 'default' => $defaultValue, 'rootVarName' => $fielddata['title'], 'rowdivid' => is_null($rowdivid) ? '' : $rowdivid, 'aid' => $aid, 'sqid' => $sqid); $this->knownVars[$sgqa] = $varInfo_Code; $this->qcode2sgqa[$varName] = $sgqa; $this->jsVar2qid[$jsVarName] = $questionNum; $this->qcode2sgq[$fielddata['title']] = $surveyid . 'X' . $groupNum . 'X' . $questionNum; // Create JavaScript arrays $this->alias2varName[$varName] = array('jsName' => $jsVarName, 'jsPart' => "'" . $varName . "':'" . $jsVarName . "'"); $this->alias2varName[$sgqa] = array('jsName' => $jsVarName, 'jsPart' => "'" . $sgqa . "':'" . $jsVarName . "'"); $this->varNameAttr[$jsVarName] = "'" . $jsVarName . "':{ " . "'jsName':'" . $jsVarName . "','jsName_on':'" . $jsVarName_on . "','sgqa':'" . $sgqa . "','qid':" . $questionNum . ",'gid':" . $groupNum . ",'type':'" . $type . "','default':'" . (is_null($defaultValue) ? '' : str_replace("'", "\\'", $defaultValue)) . "','rowdivid':'" . (is_null($rowdivid) ? '' : $rowdivid) . "','onlynum':'" . ($onlynum ? '1' : '') . "','gseq':" . $groupSeq . $ansList; if ($type == 'M' || $type == 'P') { $this->varNameAttr[$jsVarName] .= ",'question':'" . htmlspecialchars(preg_replace('/[[:space:]]/', ' ', $question), ENT_QUOTES) . "'"; } $this->varNameAttr[$jsVarName] .= "}"; } $this->q2subqInfo = $q2subqInfo; // Now set tokens if (Survey::model()->hasTokens($surveyid) && isset($_SESSION[$this->sessid]['token']) && $_SESSION[$this->sessid]['token'] != '') { //Gather survey data for tokenised surveys, for use in presenting questions $this->knownVars['TOKEN:TOKEN'] = array('code' => $_SESSION[$this->sessid]['token'], 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); $token = Token::model($surveyid)->findByToken($_SESSION[$this->sessid]['token']); foreach ($token as $key => $val) { $this->knownVars["TOKEN:" . strtoupper($key)] = array('code' => $anonymized ? '' : $val, 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } } else { // Read list of available tokens from the tokens table so that preview and error checking works correctly $attrs = array_keys(getTokenFieldsAndNames($surveyid)); $blankVal = array('code' => '', 'type' => '', 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); foreach ($attrs as $key) { if (preg_match('/^(firstname|lastname|email|usesleft|token|attribute_\\d+)$/', $key)) { $this->knownVars['TOKEN:' . strtoupper($key)] = $blankVal; } } } // set default value for reserved 'this' variable $this->knownVars['this'] = array('jsName_on' => '', 'jsName' => '', 'readWrite' => '', 'hidden' => '', 'question' => 'this', 'qid' => '', 'gid' => '', 'grelevance' => '', 'relevance' => '', 'SQrelevance' => '', 'qcode' => 'this', 'qseq' => '', 'gseq' => '', 'type' => '', 'sgqa' => '', 'rowdivid' => '', 'ansList' => '', 'ansArray' => array(), 'scale_id' => '', 'default' => '', 'rootVarName' => 'this', 'subqtext' => '', 'rowdivid' => ''); $this->runtimeTimings[] = array(__METHOD__ . ' - process fieldMap', microtime(true) - $now); usort($this->questionSeq2relevance, 'cmpQuestionSeq'); $this->numQuestions = count($this->questionSeq2relevance); $this->numGroups = count($this->groupSeqInfo); return true; }
/** * Create the arrays needed by ExpressionManager to process LimeSurvey strings. * The long part of this function should only be called once per page display (e.g. only if $fieldMap changes) * * @param <integer> $surveyid * @param <Boolean> $forceRefresh * @param <Boolean> $anonymized * @param <Boolean> $allOnOnePage - if true (like for survey_format), uses certain optimizations * @return boolean - true if $fieldmap had been re-created, so ExpressionManager variables need to be re-set */ private function setVariableAndTokenMappingsForExpressionManager($surveyid, $forceRefresh = false, $anonymized = false, $allOnOnePage = false) { if (isset($_SESSION['LEMforceRefresh'])) { unset($_SESSION['LEMforceRefresh']); $forceRefresh = true; } else { if (!$forceRefresh && isset($this->knownVars)) { return false; // means that those variables have been cached and no changes needed } } $now = microtime(true); $this->em->SetSurveyMode($this->surveyMode); // TODO - do I need to force refresh, or trust that createFieldMap will cache langauges properly? $fieldmap = createFieldMap($surveyid, $style = 'full', $forceRefresh, false, $_SESSION['LEMlang']); $this->sid = $surveyid; $this->runtimeTimings[] = array(__METHOD__ . '.createFieldMap', microtime(true) - $now); // LimeExpressionManager::ShowStackTrace(); $now = microtime(true); if (!isset($fieldmap)) { return false; // implies an error occurred } $this->knownVars = array(); // mapping of VarName to Value $this->qcode2sgqa = array(); $this->tempVars = array(); $this->qid2code = array(); // List of codes for each question - needed to know which to NULL if a question is irrelevant $this->jsVar2qid = array(); $this->qcode2sgq = array(); $this->alias2varName = array(); $this->varNameAttr = array(); $this->questionId2questionSeq = array(); $this->questionId2groupSeq = array(); $this->questionSeq2relevance = array(); $this->groupId2groupSeq = array(); $this->qid2validationEqn = array(); $this->groupSeqInfo = array(); $this->gseq2relevanceStatus = array(); // Since building array of allowable answers, need to know preset values for certain question types $presets = array(); $presets['G'] = array('M' => $this->gT("Male"), 'F' => $this->gT("Female")); $presets['Y'] = array('Y' => $this->gT("Yes"), 'N' => $this->gT("No")); $presets['C'] = array('Y' => $this->gT("Yes"), 'N' => $this->gT("No"), 'U' => $this->gT("Uncertain")); $presets['E'] = array('I' => $this->gT("Increase"), 'S' => $this->gT("Same"), 'D' => $this->gT("Decrease")); $this->gseq2info = $this->getGroupInfoForEM($surveyid, $_SESSION['LEMlang']); for ($i = 0; $i < count($this->gseq2info); ++$i) { $gseq = $this->gseq2info[$i]; $this->groupId2groupSeq[$gseq['gid']] = $i; // Only used for preview group } $qattr = $this->getQuestionAttributesForEM($surveyid, NULL, $_SESSION['LEMlang']); $this->qattr = $qattr; $this->runtimeTimings[] = array(__METHOD__ . ' - question_attributes_model->getQuestionAttributesForEM', microtime(true) - $now); $now = microtime(true); $this->qans = $this->getAnswerSetsForEM($surveyid, NULL, $_SESSION['LEMlang']); $this->runtimeTimings[] = array(__METHOD__ . ' - answers_model->getAnswerSetsForEM', microtime(true) - $now); $now = microtime(true); $q2subqInfo = array(); $this->multiflexiAnswers = array(); foreach ($fieldmap as $fielddata) { if (!isset($fielddata['fieldname']) || !preg_match('#^\\d+X\\d+X\\d+#', $fielddata['fieldname'])) { continue; // not an SGQA value } $sgqa = $fielddata['fieldname']; $type = $fielddata['type']; $mandatory = $fielddata['mandatory']; $fieldNameParts = explode('X', $sgqa); $groupNum = $fieldNameParts[1]; $aid = isset($fielddata['aid']) ? $fielddata['aid'] : ''; $sqid = isset($fielddata['sqid']) ? $fielddata['sqid'] : ''; $questionId = $fieldNameParts[2]; $questionNum = $fielddata['qid']; $relevance = isset($fielddata['relevance']) ? $fielddata['relevance'] : 1; $grelevance = isset($fielddata['grelevance']) ? $fielddata['grelevance'] : 1; $hidden = isset($qattr[$questionNum]['hidden']) ? $qattr[$questionNum]['hidden'] == '1' : false; $scale_id = isset($fielddata['scale_id']) ? $fielddata['scale_id'] : '0'; $preg = isset($fielddata['preg']) ? $fielddata['preg'] : NULL; // a perl regular exrpession validation function $defaultValue = isset($fielddata['defaultvalue']) ? $fielddata['defaultvalue'] : NULL; if (trim($preg) == '') { $preg = NULL; } $help = isset($fielddata['help']) ? $fielddata['help'] : ''; $other = isset($fielddata['other']) ? $fielddata['other'] : ''; if (isset($this->questionId2groupSeq[$questionNum])) { $groupSeq = $this->questionId2groupSeq[$questionNum]; } else { $groupSeq = isset($fielddata['groupSeq']) ? $fielddata['groupSeq'] : -1; $this->questionId2groupSeq[$questionNum] = $groupSeq; } if (isset($this->questionId2questionSeq[$questionNum])) { $questionSeq = $this->questionId2questionSeq[$questionNum]; } else { $questionSeq = isset($fielddata['questionSeq']) ? $fielddata['questionSeq'] : -1; $this->questionId2questionSeq[$questionNum] = $questionSeq; } if (!isset($this->groupSeqInfo[$groupSeq])) { $this->groupSeqInfo[$groupSeq] = array('qstart' => $questionSeq, 'qend' => $questionSeq); } else { $this->groupSeqInfo[$groupSeq]['qend'] = $questionSeq; // with each question, update so know ending value } // Create list of codes associated with each question $codeList = isset($this->qid2code[$questionNum]) ? $this->qid2code[$questionNum] : ''; if ($codeList == '') { $codeList = $sgqa; } else { $codeList .= '|' . $sgqa; } $this->qid2code[$questionNum] = $codeList; $readWrite = 'Y'; // Set $ansArray switch ($type) { case '!': //List - dropdown //List - dropdown case 'L': //LIST drop-down/radio-button list //LIST drop-down/radio-button list case 'O': //LIST WITH COMMENT drop-down/radio-button list + textarea //LIST WITH COMMENT drop-down/radio-button list + textarea case '1': //Array (Flexible Labels) dual scale // need scale //Array (Flexible Labels) dual scale // need scale case 'H': //ARRAY (Flexible) - Column Format //ARRAY (Flexible) - Column Format case 'F': //ARRAY (Flexible) - Row Format //ARRAY (Flexible) - Row Format case 'R': //RANKING STYLE $ansArray = isset($this->qans[$questionNum]) ? $this->qans[$questionNum] : NULL; if ($other == 'Y' && ($type == 'L' || $type == '!')) { if (preg_match('/other$/', $sgqa)) { $ansArray = NULL; // since the other variable doesn't need it } else { $_qattr = isset($qattr[$questionNum]) ? $qattr[$questionNum] : array(); if (isset($_qattr['other_replace_text']) && trim($_qattr['other_replace_text']) != '') { $othertext = trim($_qattr['other_replace_text']); } else { $othertext = $this->gT('Other:'); } $ansArray['0~-oth-'] = '0|' . $othertext; } } break; case 'A': //ARRAY (5 POINT CHOICE) radio-buttons //ARRAY (5 POINT CHOICE) radio-buttons case 'B': //ARRAY (10 POINT CHOICE) radio-buttons //ARRAY (10 POINT CHOICE) radio-buttons case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case '5': //5 POINT CHOICE radio-buttons $ansArray = NULL; break; case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case 'K': //MULTIPLE NUMERICAL QUESTION //MULTIPLE NUMERICAL QUESTION case 'Q': //MULTIPLE SHORT TEXT //MULTIPLE SHORT TEXT case ';': //ARRAY (Multi Flexi) Text //ARRAY (Multi Flexi) Text case 'S': //SHORT FREE TEXT //SHORT FREE TEXT case 'T': //LONG FREE TEXT //LONG FREE TEXT case 'U': //HUGE FREE TEXT //HUGE FREE TEXT case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'P': //Multiple choice with comments checkbox + text //Multiple choice with comments checkbox + text case 'D': //DATE //DATE case '*': //Equation //Equation case 'I': //Language Question //Language Question case '|': //File Upload //File Upload case 'X': //BOILERPLATE QUESTION $ansArray = NULL; break; case 'G': //GENDER drop-down list //GENDER drop-down list case 'Y': //YES/NO radio-buttons //YES/NO radio-buttons case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons //ARRAY (YES/UNCERTAIN/NO) radio-buttons case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons $ansArray = $presets[$type]; break; } // set $subqtext text - for display of primary sub-question $subqtext = ''; switch ($type) { default: $subqtext = isset($fielddata['subquestion']) ? $fielddata['subquestion'] : ''; break; case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case ';': //ARRAY (Multi Flexi) Text $subqtext = isset($fielddata['subquestion1']) ? $fielddata['subquestion1'] : ''; $ansList = array(); if (isset($fielddata['answerList'])) { foreach ($fielddata['answerList'] as $ans) { $ansList['1~' . $ans['code']] = $ans['code'] . '|' . $ans['answer']; } $this->multiflexiAnswers[$questionNum] = $ansList; } break; } // Set $varName (question code / questions.title), $rowdivid, $csuffix, $sqsuffix, and $question $rowdivid = NULL; // so that blank for types not needing it. $sqsuffix = ''; switch ($type) { case '!': //List - dropdown //List - dropdown case '5': //5 POINT CHOICE radio-buttons //5 POINT CHOICE radio-buttons case 'D': //DATE //DATE case 'G': //GENDER drop-down list //GENDER drop-down list case 'I': //Language Question //Language Question case 'L': //LIST drop-down/radio-button list //LIST drop-down/radio-button list case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case 'O': //LIST WITH COMMENT drop-down/radio-button list + textarea //LIST WITH COMMENT drop-down/radio-button list + textarea case 'S': //SHORT FREE TEXT //SHORT FREE TEXT case 'T': //LONG FREE TEXT //LONG FREE TEXT case 'U': //HUGE FREE TEXT //HUGE FREE TEXT case 'X': //BOILERPLATE QUESTION //BOILERPLATE QUESTION case 'Y': //YES/NO radio-buttons //YES/NO radio-buttons case '|': //File Upload //File Upload case '*': //Equation $csuffix = ''; $sqsuffix = ''; $varName = $fielddata['title']; if ($fielddata['aid'] != '') { $varName .= '_' . $fielddata['aid']; } $question = $fielddata['question']; break; case '1': //Array (Flexible Labels) dual scale $csuffix = $fielddata['aid'] . '#' . $fielddata['scale_id']; $sqsuffix = '_' . $fielddata['aid']; $varName = $fielddata['title'] . '_' . $fielddata['aid'] . '_' . $fielddata['scale_id']; $question = $fielddata['subquestion'] . '[' . $fielddata['scale'] . ']'; // $question = $fielddata['question'] . ': ' . $fielddata['subquestion'] . '[' . $fielddata['scale'] . ']'; $rowdivid = substr($sgqa, 0, -2); break; case 'A': //ARRAY (5 POINT CHOICE) radio-buttons //ARRAY (5 POINT CHOICE) radio-buttons case 'B': //ARRAY (10 POINT CHOICE) radio-buttons //ARRAY (10 POINT CHOICE) radio-buttons case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons //ARRAY (YES/UNCERTAIN/NO) radio-buttons case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons //ARRAY (Increase/Same/Decrease) radio-buttons case 'F': //ARRAY (Flexible) - Row Format //ARRAY (Flexible) - Row Format case 'H': //ARRAY (Flexible) - Column Format // note does not have javatbd equivalent - so array filters don't work on it //ARRAY (Flexible) - Column Format // note does not have javatbd equivalent - so array filters don't work on it case 'K': //MULTIPLE NUMERICAL QUESTION // note does not have javatbd equivalent - so array filters don't work on it, but need rowdivid to process validations //MULTIPLE NUMERICAL QUESTION // note does not have javatbd equivalent - so array filters don't work on it, but need rowdivid to process validations case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'P': //Multiple choice with comments checkbox + text //Multiple choice with comments checkbox + text case 'Q': //MULTIPLE SHORT TEXT // note does not have javatbd equivalent - so array filters don't work on it //MULTIPLE SHORT TEXT // note does not have javatbd equivalent - so array filters don't work on it case 'R': //RANKING STYLE // note does not have javatbd equivalent - so array filters don't work on it $csuffix = $fielddata['aid']; $varName = $fielddata['title'] . '_' . $fielddata['aid']; $question = $fielddata['subquestion']; // $question = $fielddata['question'] . ': ' . $fielddata['subquestion']; if ($type != 'H') { if ($type == 'P' && preg_match("/comment\$/", $sgqa)) { // $rowdivid = substr($sgqa,0,-7); } else { $sqsuffix = '_' . $fielddata['aid']; $rowdivid = $sgqa; } } break; case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case ';': //ARRAY (Multi Flexi) Text $csuffix = $fielddata['aid']; $sqsuffix = '_' . substr($fielddata['aid'], 0, strpos($fielddata['aid'], '_')); $varName = $fielddata['title'] . '_' . $fielddata['aid']; $question = $fielddata['subquestion1'] . '[' . $fielddata['subquestion2'] . ']'; // $question = $fielddata['question'] . ': ' . $fielddata['subquestion1'] . '[' . $fielddata['subquestion2'] . ']'; $rowdivid = substr($sgqa, 0, strpos($sgqa, '_')); break; } // $onlynum $onlynum = false; // the default switch ($type) { case 'K': //MULTIPLE NUMERICAL QUESTION //MULTIPLE NUMERICAL QUESTION case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case ':': //ARRAY (Multi Flexi) 1 to 10 $onlynum = true; break; case '*': // Equation // Equation case ';': //ARRAY (Multi Flexi) Text //ARRAY (Multi Flexi) Text case 'Q': //MULTIPLE SHORT TEXT //MULTIPLE SHORT TEXT case 'S': //SHORT FREE TEXT if (isset($qattr[$questionNum]['numbers_only']) && $qattr[$questionNum]['numbers_only'] == '1') { $onlynum = true; } break; case 'L': //LIST drop-down/radio-button list //LIST drop-down/radio-button list case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'P': //Multiple choice with comments checkbox + text if (isset($qattr[$questionNum]['other_numbers_only']) && $qattr[$questionNum]['other_numbers_only'] == '1' && preg_match('/other$/', $sgqa)) { $onlynum = true; } break; default: break; } // Set $jsVarName_on (for on-page variables - e.g. answerSGQA) and $jsVarName (for off-page variables; the primary name - e.g. javaSGQA) switch ($type) { case 'R': //RANKING STYLE $jsVarName_on = 'fvalue_' . $fieldNameParts[2]; $jsVarName = 'java' . $sgqa; break; case 'D': //DATE //DATE case 'N': //NUMERICAL QUESTION TYPE //NUMERICAL QUESTION TYPE case 'S': //SHORT FREE TEXT //SHORT FREE TEXT case 'T': //LONG FREE TEXT //LONG FREE TEXT case 'U': //HUGE FREE TEXT //HUGE FREE TEXT case 'Q': //MULTIPLE SHORT TEXT //MULTIPLE SHORT TEXT case 'K': //MULTIPLE NUMERICAL QUESTION //MULTIPLE NUMERICAL QUESTION case 'X': //BOILERPLATE QUESTION $jsVarName_on = 'answer' . $sgqa; $jsVarName = 'java' . $sgqa; break; case '!': //List - dropdown if (preg_match("/other\$/", $sgqa)) { $jsVarName = 'java' . $sgqa; $jsVarName_on = 'othertext' . substr($sgqa, 0, -5); } else { $jsVarName = 'java' . $sgqa; $jsVarName_on = $jsVarName; } break; case 'L': //LIST drop-down/radio-button list if (preg_match("/other\$/", $sgqa)) { $jsVarName = 'java' . $sgqa; $jsVarName_on = 'answer' . $sgqa . "text"; } else { $jsVarName = 'java' . $sgqa; $jsVarName_on = $jsVarName; } break; case '5': //5 POINT CHOICE radio-buttons //5 POINT CHOICE radio-buttons case 'G': //GENDER drop-down list //GENDER drop-down list case 'I': //Language Question //Language Question case 'Y': //YES/NO radio-buttons //YES/NO radio-buttons case '*': //Equation //Equation case '1': //Array (Flexible Labels) dual scale //Array (Flexible Labels) dual scale case 'A': //ARRAY (5 POINT CHOICE) radio-buttons //ARRAY (5 POINT CHOICE) radio-buttons case 'B': //ARRAY (10 POINT CHOICE) radio-buttons //ARRAY (10 POINT CHOICE) radio-buttons case 'C': //ARRAY (YES/UNCERTAIN/NO) radio-buttons //ARRAY (YES/UNCERTAIN/NO) radio-buttons case 'E': //ARRAY (Increase/Same/Decrease) radio-buttons //ARRAY (Increase/Same/Decrease) radio-buttons case 'F': //ARRAY (Flexible) - Row Format //ARRAY (Flexible) - Row Format case 'H': //ARRAY (Flexible) - Column Format //ARRAY (Flexible) - Column Format case 'M': //Multiple choice checkbox //Multiple choice checkbox case 'O': //LIST WITH COMMENT drop-down/radio-button list + textarea if ($type == 'O' && preg_match('/_comment$/', $varName)) { $jsVarName_on = 'answer' . $sgqa; } else { $jsVarName_on = 'java' . $sgqa; } $jsVarName = 'java' . $sgqa; break; case ':': //ARRAY (Multi Flexi) 1 to 10 //ARRAY (Multi Flexi) 1 to 10 case ';': //ARRAY (Multi Flexi) Text $jsVarName = 'java' . $sgqa; $jsVarName_on = 'answer' . $sgqa; break; case '|': //File Upload // Only want the use the one that ends in '_filecount' // $goodcode = preg_replace("/^(.*?)(_filecount)?$/","$1",$sgqa); // $jsVarName = $goodcode . '_filecount'; $jsVarName = $sgqa; $jsVarName_on = $jsVarName; break; case 'P': //Multiple choice with comments checkbox + text if (preg_match("/(other|comment)\$/", $sgqa)) { $jsVarName_on = 'answer' . $sgqa; // is this true for survey.php and not for group.php? $jsVarName = 'java' . $sgqa; } else { $jsVarName = 'java' . $sgqa; $jsVarName_on = $jsVarName; } break; } if (!is_null($rowdivid) || $type == 'L' || $type == 'N' || $type == '!' || !is_null($preg) || $type == 'S' || $type == 'T' || $type == 'U' || $type == '|') { if (!isset($q2subqInfo[$questionNum])) { $q2subqInfo[$questionNum] = array('qid' => $questionNum, 'qseq' => $questionSeq, 'gseq' => $groupSeq, 'sgqa' => $surveyid . 'X' . $groupNum . 'X' . $questionNum, 'mandatory' => $mandatory, 'varName' => $varName, 'type' => $type, 'fieldname' => $sgqa, 'preg' => $preg, 'rootVarName' => $fielddata['title']); } if (!isset($q2subqInfo[$questionNum]['subqs'])) { $q2subqInfo[$questionNum]['subqs'] = array(); } if ($type == 'L' || $type == '!') { if (!is_null($ansArray)) { foreach (array_keys($ansArray) as $key) { $parts = explode('~', $key); if ($parts[1] == '-oth-') { $parts[1] = 'other'; } $q2subqInfo[$questionNum]['subqs'][] = array('rowdivid' => $surveyid . 'X' . $groupNum . 'X' . $questionNum . $parts[1], 'varName' => $varName, 'sqsuffix' => '_' . $parts[1]); } } } else { if ($type == 'N' || $type == 'S' || $type == 'T' || $type == 'U') { $q2subqInfo[$questionNum]['subqs'][] = array('varName' => $varName, 'rowdivid' => $surveyid . 'X' . $groupNum . 'X' . $questionNum, 'jsVarName' => 'java' . $surveyid . 'X' . $groupNum . 'X' . $questionNum, 'jsVarName_on' => $jsVarName_on); } else { $q2subqInfo[$questionNum]['subqs'][] = array('rowdivid' => $rowdivid, 'varName' => $varName, 'jsVarName_on' => $jsVarName_on, 'jsVarName' => $jsVarName, 'csuffix' => $csuffix, 'sqsuffix' => $sqsuffix); } } } $ansList = ''; if (isset($ansArray) && !is_null($ansArray)) { $answers = array(); foreach ($ansArray as $key => $value) { $answers[] = "'" . $key . "':'" . htmlspecialchars(preg_replace('/[[:space:]]/', ' ', $value), ENT_QUOTES) . "'"; } $ansList = ",'answers':{ " . implode(",", $answers) . "}"; } // Set mappings of variable names to needed attributes $varInfo_Code = array('jsName_on' => $jsVarName_on, 'jsName' => $jsVarName, 'readWrite' => $readWrite, 'hidden' => $hidden, 'question' => $question, 'qid' => $questionNum, 'gid' => $groupNum, 'grelevance' => $grelevance, 'relevance' => $relevance, 'qcode' => $varName, 'qseq' => $questionSeq, 'gseq' => $groupSeq, 'type' => $type, 'sgqa' => $sgqa, 'ansList' => $ansList, 'ansArray' => $ansArray, 'scale_id' => $scale_id, 'default' => $defaultValue, 'rootVarName' => $fielddata['title'], 'subqtext' => $subqtext, 'rowdivid' => is_null($rowdivid) ? '' : $rowdivid, 'onlynum' => $onlynum); $this->questionSeq2relevance[$questionSeq] = array('relevance' => $relevance, 'grelevance' => $grelevance, 'qid' => $questionNum, 'qseq' => $questionSeq, 'gseq' => $groupSeq, 'jsResultVar_on' => $jsVarName_on, 'jsResultVar' => $jsVarName, 'type' => $type, 'hidden' => $hidden, 'gid' => $groupNum, 'mandatory' => $mandatory, 'eqn' => $type == '*' ? $question : '', 'help' => $help, 'qtext' => $fielddata['question'], 'code' => $varName, 'other' => $other, 'default' => $defaultValue, 'rootVarName' => $fielddata['title'], 'rowdivid' => is_null($rowdivid) ? '' : $rowdivid, 'aid' => $aid, 'sqid' => $sqid); $this->knownVars[$sgqa] = $varInfo_Code; $this->qcode2sgqa[$varName] = $sgqa; $this->jsVar2qid[$jsVarName] = $questionNum; $this->qcode2sgq[$fielddata['title']] = $surveyid . 'X' . $groupNum . 'X' . $questionNum; // Create JavaScript arrays $this->alias2varName[$varName] = array('jsName' => $jsVarName, 'jsPart' => "'" . $varName . "':'" . $jsVarName . "'"); $this->alias2varName[$sgqa] = array('jsName' => $jsVarName, 'jsPart' => "'" . $sgqa . "':'" . $jsVarName . "'"); $this->varNameAttr[$jsVarName] = "'" . $jsVarName . "':{ " . "'jsName':'" . $jsVarName . "','jsName_on':'" . $jsVarName_on . "','sgqa':'" . $sgqa . "','qid':" . $questionNum . ",'gid':" . $groupNum . ",'type':'" . $type . "','default':'" . (is_null($defaultValue) ? '' : $defaultValue) . "','rowdivid':'" . (is_null($rowdivid) ? '' : $rowdivid) . "','onlynum':'" . ($onlynum ? '1' : '') . "','gseq':" . $groupSeq . $ansList; if ($type == 'M' || $type == 'P') { $this->varNameAttr[$jsVarName] .= ",'question':'" . htmlspecialchars(preg_replace('/[[:space:]]/', ' ', $question), ENT_QUOTES) . "'"; } $this->varNameAttr[$jsVarName] .= "}"; } $this->q2subqInfo = $q2subqInfo; // Now set tokens if (isset($_SESSION['token']) && $_SESSION['token'] != '') { //Gather survey data for tokenised surveys, for use in presenting questions $_SESSION['thistoken'] = getTokenData($surveyid, $_SESSION['token']); $this->knownVars['TOKEN:TOKEN'] = array('code' => $_SESSION['token'], 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); //queXS Addition $this->knownVars['TOKEN:CASEID'] = array('code' => $_SESSION['token'], 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } else { //queXS Addition $this->knownVars['TOKEN:CASEID'] = array('code' => 0, 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } if (isset($_SESSION['thistoken'])) { foreach (array_keys($_SESSION['thistoken']) as $tokenkey) { if ($anonymized) { $val = ""; } else { $val = $_SESSION['thistoken'][$tokenkey]; } $key = "TOKEN:" . strtoupper($tokenkey); $this->knownVars[$key] = array('code' => $val, 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } //queXS Addition //Add all sample variables for this case global $connect; $use_call = true; if (strlen($_SESSION['token']) == 15) { $use_call = false; } if ($use_call) { $sql = "SELECT sivr.var,sv.val\n\t\t\t\tFROM sample_var as sv, `case` as c, `call` as cl, `sample_import_var_restrict` as sivr\n\t\t\t\tWHERE c.sample_id = sv.sample_id\n\t\t\t\tAND c.case_id = cl.case_id\n\t\t\t\tAND sv.var_id = sivr.var_id\n\t\t\t\tAND cl.call_id = '{$_SESSION['token']}'"; } else { $sql = "SELECT sivr.var,sv.val\n\t\t\t\tFROM sample_var as sv, `case` as c, `sample_import_var_restrict` as sivr\n\t\t\t\tWHERE c.sample_id = sv.sample_id\n\t\t\t\tAND sv.var_id = sivr.var_id\n\t\t\t\tAND c.token = '{$_SESSION['token']}'"; } $queXSrs = $connect->GetAssoc($sql); foreach ($queXSrs as $samplekey => $val) { $key = "SAMPLE:" . strtoupper($samplekey); $this->knownVars[$key] = array('code' => $val, 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } if ($use_call) { $osql = "FROM operator as o, `call` as cl\n\t\t\t\t WHERE o.operator_id = cl.operator_id\n\t\t\t\t AND cl.call_id = '{$_SESSION['token']}'"; $rsql = "FROM respondent as r, `call` as cl\n\t\t\t \t WHERE cl.call_id = '{$_SESSION['token']}'\n\t\t\t\t AND r.respondent_id = cl.respondent_id"; } else { $osql = "FROM operator as o, `case` as c\n\t \t\t\t WHERE c.token = '{$_SESSION['token']}'\n\t\t\t\t AND o.operator_id = c.current_operator_id"; $rsql = "FROM respondent as r, `case` as c, call_attempt as ca\n\t\t\t \t WHERE c.token = '{$_SESSION['token']}'\n\t\t\t\t AND ca.case_id = c.case_id\n\t\t\t\t AND ca.end IS NULL\n\t\t\t\t AND r.respondent_id = ca.respondent_id"; } //add operator and respondent details $this->knownVars["OPERATOR:FIRSTNAME"] = array('code' => $connect->GetOne("\tSELECT o.firstName " . $osql), 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); $this->knownVars["OPERATOR:LASTNAME"] = array('code' => $connect->GetOne("\tSELECT o.lastName " . $osql), 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); $this->knownVars["RESPONDENT:FIRSTNAME"] = array('code' => $connect->GetOne("\tSELECT r.firstName " . $rsql), 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); $this->knownVars["RESPONDENT:LASTNAME"] = array('code' => $connect->GetOne("\tSELECT r.lastName " . $rsql), 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } else { // Read list of available tokens from the tokens table so that preview and error checking works correctly $attrs = GetAttributeFieldNames($surveyid, false); $blankVal = array('code' => '', 'type' => '', 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); foreach ($attrs as $key) { if (preg_match('/^(firstname|lastname|email|usesleft|token|attribute_\\d+)$/', $key)) { $this->knownVars['TOKEN:' . strtoupper($key)] = $blankVal; } } //queXS Addition //Add all sample variables for this questionnaire global $connect; $sql = "SELECT sivr.var,sv.val\n\t\t\t\tFROM `questionnaire` as q, questionnaire_sample as qs, sample_var as sv, `sample_import_var_restrict` as sivr\n\t\t\t\tWHERE q.lime_sid = {$surveyid}\n\t\t\t\tAND qs.questionnaire_id = q.questionnaire_id\n\t\t\t\tAND sivr.sample_import_id = qs.sample_import_id \n\t\t\t\tAND sv.var_id = sivr.var_id \n\t\t\t\tGROUP BY qs.sample_import_id,sivr.var"; $queXSrs = $connect->GetAssoc($sql); foreach ($queXSrs as $samplekey => $val) { $key = "SAMPLE:" . strtoupper($samplekey); $this->knownVars[$key] = array('code' => $val, 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } $oa = array("OPERATOR:FIRSTNAME", "OPERATOR:LASTNAME", "RESPONDENT:FIRSTNAME", "RESPONDENT:LASTNAME"); foreach ($oa as $o) { $this->knownVars[$o] = array('code' => "", 'jsName_on' => '', 'jsName' => '', 'readWrite' => 'N'); } } // set default value for reserved 'this' variable $this->knownVars['this'] = array('jsName_on' => '', 'jsName' => '', 'readWrite' => '', 'hidden' => '', 'question' => 'this', 'qid' => '', 'gid' => '', 'grelevance' => '', 'relevance' => '', 'qcode' => 'this', 'qseq' => '', 'gseq' => '', 'type' => '', 'sgqa' => '', 'rowdivid' => '', 'ansList' => '', 'ansArray' => array(), 'scale_id' => '', 'default' => '', 'rootVarName' => 'this', 'subqtext' => '', 'rowdivid' => ''); $this->runtimeTimings[] = array(__METHOD__ . ' - process fieldMap', microtime(true) - $now); usort($this->questionSeq2relevance, 'cmpQuestionSeq'); $this->numQuestions = count($this->questionSeq2relevance); $this->numGroups = count($this->groupSeqInfo); return true; }