LimeExpressionManager

package

Default

Methods

Prevent users to clone the instance

__clone()

A private constructor; prevents direct creation of object

__construct()

Process all question attributes that apply to EM (1) subquestion-level relevance: e.g. array_filter, array_filter_exclude, relevance equations entered in SQ-mask (2) Validations: e.g. min/max number of answers; min/max/eq sum of answers

_CreateSubQLevelRelevanceAndValidationEqns(integer|null $onlyThisQseq = null): void

Arguments

$onlyThisQseq

integer|null

  • only process these attributes for the specified question

_GetVarAttribute

_GetVarAttribute( $name, $attr, $default,integer $gseq,integer $qseq)

Arguments

$name

$attr

$default

$gseq

integer

$qseq

integer

_ProcessGroupRelevance

_ProcessGroupRelevance(integer $groupSeq): void

Arguments

$groupSeq

integer

Compute Relevance, processing $eqn to get a boolean value. If there are syntax errors, return false.

_ProcessRelevance(string $eqn,string $questionNum = null, $gseq = null,string $jsResultVar = null,string $type = null,integer $hidden): boolean

Arguments

$eqn

string

  • the relevance equation

$questionNum

string

  • needed to align question-level relevance and tailoring

$gseq

$jsResultVar

string

  • this variable determines whether irrelevant questions are hidden

$type

string

  • question type

$hidden

integer

  • whether question should always be hidden

Response

boolean

Create JavaScript needed to process subquestion-level relevance (e.g. for array_filter and _exclude)

_ProcessSubQRelevance(string $eqn,string $questionNum = null,string $rowdivid = null,string $type = null,string $qtype = null,string $sgqa = null,string $isExclusive = '',string $irrelevantAndExclusive = ''): boolean

Arguments

$eqn

string

  • the equation to parse

$questionNum

string

  • the question number - needed to align relavance and tailoring blocks

$rowdivid

string

  • the javascript ID that needs to be shown/hidden in order to control array_filter visibility

$type

string

  • the type of subquestion relevance (e.g. 'array_filter', 'array_filter_exclude')

$qtype

string

$sgqa

string

$isExclusive

string

$irrelevantAndExclusive

string

Response

boolean

Recursively find all questions that logically preceded the current array_filter or array_filter_exclude request Note, must support: (a) semicolon-separated list of $qroot codes for either array_filter or array_filter_exclude (b) mixed history of array_filter and array_filter_exclude values

_recursivelyFindAntecdentArrayFilters(string $qroot,array $aflist,array $afelist): array

Arguments

$qroot

string

  • the question root variable name

$aflist

array

  • the list of array_filter $qroot codes

$afelist

array

  • the list of array_filter_exclude $qroot codes

Response

array

Write values to database.

_UpdateValuesInDatabase(boolean $finished = false): string

Arguments

$finished

boolean

  • true if the survey needs to be finalized

Response

string

Check a group and all of the questions it contains

_ValidateGroup(integer $groupSeq,boolean $force = false): array

Arguments

$groupSeq

integer

  • the index-0 sequence number for this group

$force

boolean

: force validation to true, even if there are error

Response

array

Detailed information about this group

For the current set of questions (whether in survey, gtoup, or question-by-question mode), assesses the following: (a) mandatory - if so, then all relevant subquestions must be answered (e.g. pay attention to array_filter and array_filter_exclude) (b) always-hidden (c) relevance status - including subquestion-level relevance (d) answered - if $_SESSION[$LEM->sessid][sgqa]=='' or NULL, then it is not answered (e) validity - whether relevant questions pass their validity tests

_ValidateQuestion(integer $questionSeq,boolean $force = false): array

Arguments

$questionSeq

integer

  • the 0-index sequence number for this question

$force

boolean

: force validation to true, even if there are error, this allow to save in DB even with error

Response

array

Array of information about this question and its subquestions

Check the entire survey

_ValidateSurvey(boolean $force = false): array

Arguments

$force

boolean

: force validation to true, even if there are error, used at survey start to fill EM

Response

array

with information on validated question

Add a flash message to state-key 'frontend{survey id}' The flash messages are templatereplaced in startpage.tstpl, {FLASHMESSAGE}

addFrontendFlashMessage(string $type,string $message,integer $surveyid): void
static
todo

: validate if it work : unsure it was shown always to user (nojs ?)

Arguments

$type

string

Yii type of flash: error, notice, 'success'

$message

string

$surveyid

integer

Set or log an invalid answer string

addValidityString(string $sgqa, $value,string $message,boolean $add = true): void

Arguments

$sgqa

string

: the SGQ (answer column / SGQA)

$value

$message

string

: the message

$add

boolean

: add it to current validity or only og it

Check a validity of an answer, Put the string to show to user $this->invalidAnswerString See mantis #10827, #11611 and #14649

checkValidityAnswer(string $type,string $value,string $sgq,array $qinfo,boolean $set = true): boolean
static
Throws
\Exception

Arguments

$type

string

: question type

$value

string

: the value

$sgq

string

: the sgqa

$qinfo

array

: an array with information from question with mandatory ['qid'=>$qid] , optional (but must be 'other'=>$other)

$set

boolean

: update the invalid string or not. Used for #14649 (invalid default value)

Response

boolean

true : if question is OK to be put in session, false if must be set to null

If $qid is set, returns the relevance equation generated from conditions (or NULL if there are no conditions for that $qid) If $qid is NULL, returns an array of relevance equations generated from Condition, keyed on the question ID

ConvertConditionsToRelevance(integer $surveyId,integer|null $qid = null): array
static

Arguments

$surveyId

integer

$qid

integer|null

  • if passed, only generates relevance equation for that question - otherwise genereates for all questions with conditions

Response

array

of generated relevance strings, indexed by $qid

Convert non-latin numerics in string to latin numerics Used for datepicker (Hindi, Arabic numbers)

convertNonLatinNumerics(string $str,string $lang): string
static

Arguments

$str

string

$lang

string

Response

string

Should be called after each group finishes

FinishProcessingGroup(boolean|null $skipReprocessing = false): void
static

Arguments

$skipReprocessing

boolean|null

Should be called at end of each page

FinishProcessingPage(): void
static

End public HTML

FinishProcessPublicPage( $applyJavaScriptAnyway = false): string|null
static
todo

: add directly hidden input in page without return it.

Arguments

$applyJavaScriptAnyway

Response

string|null

: hidden inputs needed for relevance

Expand "self.suffix" and "that.qcode.suffix" into canonical list of variable names

GetAllVarNamesForQ(integer $qseq,string $varname): string
static

Arguments

$qseq

integer

$varname

string

Response

string

Return array of language-specific answer codes

getAnswerSetsForEM(integer|null $surveyid = null,string|null $lang = null): array

Arguments

$surveyid

integer|null

$lang

string|null

Response

array

getConditionsForEM

getConditionsForEM( $surveyid, $qid = null)
static

Arguments

$surveyid

$qid

Return a formatted table showing how much time each part of EM consumed

GetDebugTimingMessage(): string
static

Response

string

Get the current public language

getEMlanguage(): \string;
static

Response

\string;

Get array of info needed to display the Group Index

GetGroupIndexInfo(string $gseq = null): array
static

Arguments

$gseq

string

Response

array

Returns group info needed for indexes

getGroupInfoForEM(integer $surveyid,string|null $sLanguage = null): array

Arguments

$surveyid

integer

$sLanguage

string|null

Response

array

Translate GID to 0-index Group Sequence number

GetGroupSeq(integer $gid): integer
static

Arguments

$gid

integer

Response

integer

Get last move information, optionally clearing the substitution cache

GetLastMoveResult(boolean $clearSubstitutionInfo = false): array|null
static

Arguments

$clearSubstitutionInfo

boolean

Response

array|null

Used to show potential syntax errors of processing Relevance or Equations.

GetLastPrettyPrintExpression(): string
static

Response

string

Return array database name as key, LEM name as value

getLEMqcode2sgqa(integer $iSurveyId): array
static

Arguments

$iSurveyId

integer

Response

array

*@example (['gender'] => '38612X10X145')

Returns the survey ID of the EM singleton

getLEMsurveyId(): integer
static

Response

integer

Return array of language-specific answer codes

getQuestionAttributesForEM(integer|null $surveyid,integer|null $qid,string|null $lang = ''): array

Arguments

$surveyid

integer|null

$qid

integer|null

$lang

string|null

Response

array

Get array of info needed to display the Question Index

GetQuestionIndexInfo(): array
static

Response

array

Get question sequence number from QID

GetQuestionSeq(integer $qid): integer
static

Arguments

$qid

integer

Response

integer

GetQuestionStatus

GetQuestionStatus( $qid)
static

Arguments

$qid

Return the regexp used to check if suffix is valid

getRegexpValidAttributes(): string
static

Response

string

GetRelevanceAndTailoringJavaScript

GetRelevanceAndTailoringJavaScript( $bReturnArray = false)
static

Arguments

$bReturnArray

Return entries needed to build the navigation index

GetStepIndexInfo(integer|null $step = null): array
static

Arguments

$step

integer|null

  • if specified, return a single value, otherwise return entire array

Response

array

  • will be either question or group-level, depending upon $surveyMode

getUpdatedValues

getUpdatedValues(): array

Response

array

return the actual validity string , and reset the variable used ($_SESSION)

getValidityString(string $sgqa): string|null
static

Arguments

$sgqa

string

: the SGQ (answer name)

Response

string|null

GetVarAttribute

GetVarAttribute( $name,string|null $attr, $default,integer $gseq,integer $qseq)
static

Arguments

$name

$attr

string|null

$default

$gseq

integer

$qseq

integer

Return whether group $gseq is relevant

GroupIsIrrelevantOrHidden(integer $gseq): boolean
static

Arguments

$gseq

integer

Response

boolean

Returns true if the group is relevant and should be shown

GroupIsRelevant(integer $gid): boolean
static

Arguments

$gid

integer

Response

boolean

gT

gT(string $string, $escapemode = 'html')

Arguments

$string

string

$escapemode

return a value entered by user to be shown or used in expression

htmlSpecialCharsUserValue(string $string): string
static

Arguments

$string

string

Response

string

Did LEM is currently initialized

isInitialized(): boolean
static

Response

boolean

isValidVariable

isValidVariable( $varName)
static

Arguments

$varName

Jump to a specific question or group sequence. If jumping forward, it re-validates everything in between

JumpTo(integer $seq,string|false $preview = false,boolean $processPOST = true,boolean $force = false,boolean $changeLang = false): array
static

Arguments

$seq

integer

  • the sequential step

$preview

string|false

@see var $sPreviewMode

$processPOST

boolean

  • add the updated value to be saved in the database

$force

boolean

  • if true, then skip validation of current group (e.g. will jump even if there are errors)

$changeLang

boolean

Response

array

$this->lastMoveResult

This function loads the relevant data about tokens for a survey.

loadTokenInformation(integer $iSurveyId,string|null $sToken = null,boolean|null $bAnonymize = false): void

If specific token is not given it loads empty values, this is used for question previewing and the like.

Arguments

$iSurveyId

integer

$sToken

string|null

$bAnonymize

boolean|null

NavigateBackwards

NavigateBackwards(): mixed
static

Response

mixed

NavigateForwards

NavigateForwards(boolean $force = false): array|null
static

Arguments

$force

boolean

  • if true, continue to go forward even if there are violations to the mandatory and/or validity rules

Response

array|null

  • lastMoveResult

ngT

ngT(string $sTextToTranslate,integer $number, $escapemode = 'html')

Arguments

$sTextToTranslate

string

$number

integer

$escapemode

Check the relevance status of all questions on or before the current group.

ProcessAllNeededRelevance(string|null $onlyThisQseq = null, $groupSeq = null): void

This generates needed JavaScript for dynamic relevance, and sets flags about which questions and groups are relevant

Arguments

$onlyThisQseq

string|null

$groupSeq

Cleanse the $_POSTed data and update $_SESSION variables accordingly

ProcessCurrentResponses()
static

Compute Relevance, processing $eqn to get a boolean value. If there are syntax errors, return false.

ProcessRelevance(string $eqn,string $questionNum = null,string $jsResultVar = null,string $type = null,integer $hidden): boolean
static

Arguments

$eqn

string

  • the relevance equation

$questionNum

string

  • needed to align question-level relevance and tailoring

$jsResultVar

string

  • this variable determines whether irrelevant questions are hidden

$type

string

  • question type

$hidden

integer

  • whether question should always be hidden

Response

boolean

Translate all Expressions, Macros, registered variables, etc. in $string for current step

ProcessStepString(string $string,array $replacementFields = array(),integer $numRecursionLevels = 3,boolean $static = false): string
static

Arguments

$string

string

  • the string to be replaced

$replacementFields

array

  • optional replacement values

$numRecursionLevels

integer

  • the number of times to recursively subtitute values in this string

$static

boolean

  • return static string (without any javascript)

Response

string

  • the original $string with all replacements done.

Translate all Expressions, Macros, registered variables, etc. in $string

ProcessString(string $string,integer $questionNum = null,array|null $replacementFields = array(),integer $numRecursionLevels = 1,integer $whichPrettyPrintIteration = 1,boolean $noReplacements = false,boolean $timeit = true,boolean $staticReplacement = false): string
static

Arguments

$string

string

  • the string to be replaced

$questionNum

integer

  • the $qid of question being replaced - needed for properly alignment of question-level relevance and tailoring

$replacementFields

array|null

  • optional replacement values

$numRecursionLevels

integer

  • the number of times to recursively subtitute values in this string

$whichPrettyPrintIteration

integer

  • if want to pretty-print the source string, which recursion level should be pretty-printed

$noReplacements

boolean

  • true if we already know that no replacements are needed (e.g. there are no curly braces)

$timeit

boolean

$staticReplacement

boolean

  • return HTML string without the system to update by javascript

Response

string

  • the original $string with all replacements done.

Return whether question $qid is relevanct

QuestionIsRelevant(integer $qid): boolean
static

Arguments

$qid

integer

Response

boolean

Reset the current temporary variable replacement Done automatically when page start or page finish ( @param array $vars

resetTempVars()
static
see self::FinishProcessPublicPage,

@see self::StartProcessingPage )

This reverses UpgradeConditionsToRelevance(). It removes Relevance for questions that have Condition

RevertUpgradeConditionsToRelevance(integer|null $surveyId = null,integer|null $qid = null): integer
static

Arguments

$surveyId

integer|null

$qid

integer|null

Response

integer

Set currentQset. Used by unit-tests.

setCurrentQset(array $val): void

Arguments

$val

array

Tells ExpressionScript Engine that something has changed enough that needs to eliminate internal caching

SetDirtyFlag(): void
static

Sets the language for ExpressionScript Engine. If the language has changed, then EM cache must be invalidated and refreshed

SetEMLanguage(string|null $lang = null): void
static

Arguments

$lang

string|null

Used for unit tests.

setKnownVars(mixed $val): void

Arguments

$val

mixed

Used for unit tests.

setPageRelevanceInfo(mixed $info): void

Arguments

$info

mixed

Set the previewmode

SetPreviewMode(string|false $previewmode = false): void
static

Arguments

$previewmode

string|false

'question', 'group', false

Set the relevance status to the $step

SetRelevanceTo(integer $seq): void
static

Arguments

$seq

integer

  • the sequential step

Set the SurveyId - really checks whether the survey you're about to work with is new, and if so, clears the LEM cache

SetSurveyId(integer|null $sid = null)
static

Arguments

$sid

integer|null

setTempVars

setTempVars(array $vars)
static

Arguments

$vars

array

Set the 'this' variable as an alias for SGQA within the code.

SetThisAsAliasForSGQA(string $sgqa): void
static

Arguments

$sgqa

string

Helper function to update a Read only value

setValueToKnowVar(string $var,string $value)
static

Arguments

$var

string

$value

string

Create the arrays needed by ExpressionManager to process LimeSurvey strings.

setVariableAndTokenMappingsForExpressionManager(integer $surveyid,boolean|null $forceRefresh = false,boolean|null $anonymized = false): boolean|null

The long part of this function should only be called once per page display (e.g. only if $fieldMap changes)

todo

Keep method as-is but factor out content to new class; add unit tests for class

Arguments

$surveyid

integer

$forceRefresh

boolean|null

$anonymized

boolean|null

Response

boolean|null

  • true if $fieldmap had been re-created, so ExpressionManager variables need to be re-set

SetVariableValue

SetVariableValue(string $op,string $name,double $value): integer
static

Arguments

$op

string

$name

string

$value

double

Response

integer

ShowStackTrace

ShowStackTrace( $msg = null, &$args = null)
static

Arguments

$msg

$args

Create HTML view of the survey, showing everything that uses EM

ShowSurveyLogicFile(integer $sid,integer|null $gid = null, $qid = null,integer|null $LEMdebugLevel,boolean|null $assessments = null): array
static

Arguments

$sid

integer

$gid

integer|null

$qid

$LEMdebugLevel

integer|null

$assessments

boolean|null

Response

array

Ensures there is only one instances of LEM. Note, if switch between surveys, have to clear this cache

singleton(): \LimeExpressionManager
static

Returns an array of string parts, splitting out expressions

SplitStringOnExpressions(string $src): array
static

Arguments

$src

string

Response

array

This should be called each time a new group is started, whether on same or different pages. Sets/Clears needed internal parameters.

StartProcessingGroup(integer|null $gseq = null,boolean|null $anonymized = false,integer|null $surveyid = null,boolean|null $forceRefresh = false): void
static

Arguments

$gseq

integer|null

  • the group sequence

$anonymized

boolean|null

  • whether anonymized

$surveyid

integer|null

  • the surveyId

$forceRefresh

boolean|null

  • whether to force refresh of setting variable and token mappings (should be done rarely)

Should be first function called on each page - sets/clears internally needed variables

StartProcessingPage(boolean $allOnOnePage = false,boolean $initializeVars = false): void
static

Arguments

$allOnOnePage

boolean

  • true if StartProcessingGroup will be called multiple times on this page - does some optimizatinos

$initializeVars

boolean

  • if true, initializes the replacement variables to enable syntax highlighting on admin pages

Initialize a survey so can use EM to manage navigation

StartSurvey(integer $surveyid,string $surveyMode = 'group',array $aSurveyOptions = null,boolean $forceRefresh = false,integer $debugLevel): array
static

Arguments

$surveyid

integer

$surveyMode

string

$aSurveyOptions

array

$forceRefresh

boolean

$debugLevel

integer

Response

array

Return whether a subquestion is relevant

SubQuestionIsRelevant(string $sgqa): boolean
static

Arguments

$sgqa

string

Response

boolean

Return list of relevance equations generated from conditions

UnitTestConvertConditionsToRelevance(integer|null $surveyId = null,integer|null $qid = null): array
static

Arguments

$surveyId

integer|null

$qid

integer|null

Response

array

of relevance equations, indexed by $qid

Unit test strings containing expressions

UnitTestProcessStringContainingExpressions()
static

Unit test Relevance using a simplified syntax to represent questions.

UnitTestRelevance()
static

Add or replace fixed variable replacement for current page (or until self::resetTempVars was called)

updateReplacementFields( $replacementFields)
static

Arguments

$replacementFields

Do bulk-update/save of Condition to Relevance

UpgradeConditionsToRelevance(integer|null $surveyId = null,integer|null $qid = null): array
static

Arguments

$surveyId

integer|null

  • if NULL, processes the entire database, otherwise just the specified survey

$qid

integer|null

  • if specified, just updates that one question

Response

array

of query strings

Deprecate obsolete question attributes.

UpgradeQuestionAttributes(boolean|null $changeDB = false,integer|null $iSurveyID = null,integer|null $onlythisqid = null)
static

Arguments

$changeDB

boolean|null

  • if true, updates parameters and deletes old ones

$iSurveyID

integer|null

  • if set, then only for that survey

$onlythisqid

integer|null

  • if set, then only for this question ID

Returns true if the survey is using comma as the radix

usingCommaAsRadix(): boolean
static

Response

boolean

Properties

LimeExpressionManager is a singleton. $instance is its storage location.

instance :\LimeExpressionManager
static

Implements the recursive descent parser that processes expressions

em :\ExpressionManager
var

Type(s)

\ExpressionManager

groupRelevanceInfo

groupRelevanceInfo :array
var

Type(s)

array

The survey ID

sid :integer
var

Type(s)

integer

sum of LEM_DEBUG constants - use bitwise AND comparisons to identify which parts to use

debugLevel :integer
var

Type(s)

integer

sPreviewMode used for relevance equation and to disable save value in DB 'question' or 'group' string force relevance to 1 if needed

sPreviewMode :string|false
var

Type(s)

string|false

Collection of variable attributes, indexed by SGQA code

knownVars :array

Actual variables are stored in this structure: $knownVars[$sgqa] = array( 'jsName_on' => // the name of the javascript variable if it is defined on the current page - often 'answerSGQA' 'jsName' => // the name of the javascript variable when referenced on different pages - usually 'javaSGQA' 'readWrite' => // 'Y' for yes, 'N' for no - currently not used 'hidden' => // 1 if the question attribute 'hidden' is true, otherwise 0 'question' => // the text of the question (or subquestion) 'qid' => // the numeric question id - e.g. the Q part of the SGQA name 'gid' => // the numeric group id - e.g. the G part of the SGQA name 'grelevance' => // the group level relevance string 'relevance' => // the question level relevance string 'qcode' => // the qcode-style variable name for this question (or subquestion) 'qseq' => // the 0-based index of the question within the survey 'gseq' => // the 0-based index of the group within the survey 'type' => // the single character type code for the question 'sgqa' => // the SGQA name for the variable 'ansList' => // ansArray converted to a JavaScript fragment - e.g. ",'answers':{ 'M':'Male','F':'Female'}" 'ansArray' => // PHP array of answer strings, keyed on the answer code = e.g. array['M']='Male'; 'scale_id' => // '0' for most answers. '1' for second scale within dual-scale questions 'rootVarName' => // the root code / name / title for the question, without any subquestion or answer-level suffix. This is from the title column in the questions table 'subqtext' => // the subquestion text 'rowdivid' => // the JavaScript ID of the row identifier for a question. This is used to show/hide entire question rows 'onlynum' => // 1 if only numbers are allowed for this variable. If so, then extra processing is needed to ensure that can use comma as a decimal separator );

Reserved variables (e.g. TOKEN:xxxx) are stored with this structure: $knownVars[$token] = array( 'code' => // the static value for the variable 'type' => // '' 'jsName_on' => // '' 'jsName' => // '' 'readWrite' => // 'N' - since these are always read-only variables );

var

Type(s)

array

maps qcode varname to SGQA code

qcode2sgqa :array|null
example

= '38612X10X145'

var

Type(s)

array|null

variables temporarily set for substitution purposes temporarily mean for this page, until reset. Not for next page

tempVars :array

These are typically the LimeReplacement Fields passed in via templatereplace() Each has the following structure: array( 'code' => // the static value of the variable 'jsName_on' => // '' 'jsName' => // '' 'readWrite' => // 'N' );

var

Type(s)

array

Array of relevance information for each page (gseq), indexed by gseq.

pageRelevanceInfo :array

Within a page, it contains a sequential list of the results of each relevance equation processed array( 'qid' => // question id -- e.g. 154 'gseq' => // 0-based group sequence -- e.g. 2 'eqn' => // the raw relevance equation parsed -- e.g. "!is_empty(p2_sex)" 'result' => // the Boolean result of parsing that equation in the current context -- e.g. 0 'numJsVars' => // the number of dynamic JavaScript variables used in that equation -- e.g. 1 'relevancejs' => // the actual JavaScript to insert for that relevance equation -- e.g. "LEMif(LEManyNA('p2_sex'),'',( ! LEMempty(LEMval('p2_sex') )))" 'relevanceVars' => // a pipe-delimited list of JavaScript variables upon which that equation depends -- e.g. "java38612X12X153" 'jsResultVar' => // the JavaScript variable in which that result will be stored -- e.g. "java38612X12X154" 'type' => // the single character type of the question -- e.g. 'S' 'hidden' => // 1 if the question should always be hidden 'hasErrors' => // 1 if there were parsing errors processing that relevance equation

var

Type(s)

array

Array of array of information about HTML id to update with javascript function [[ 'questionNum' : question number 'num' : internal number of javascript function 'id' : id of HTML element 'raw' : Raw Expression 'result' : 'vars' : var used in javascript function 'js' : final javascript function ]]

pageTailorInfo :array|null
var

Array of array of information about HTML id to update with javascript function [[ 'questionNum' : question number 'num' : internal number of javascript function 'id' : id of HTML element 'raw' : Raw Expression 'result' : 'vars' : var used in javascript function 'js' : final javascript function ]]

Type(s)

array|null

internally set to true (1) for survey.php so get group-specific logging but keep javascript variable namings consistent on the page.

allOnOnePage :boolean
var

Type(s)

boolean

survey mode. One of 'survey', 'group', or 'question'

surveyMode :string
var

Type(s)

string

a set of global survey options passed from LimeSurvey

surveyOptions :array

For example, array( 'rooturl' => // URL prefix needed to be able to click on a syntax-highlighted variable name and have it open the needed editting window 'hyperlinkSyntaxHighlighting' => // true if should be able to click on variables to edit them 'active' => // 0 for inactive, 1 for active survey 'allowsave' => // 0 for do not allow save; 1 for allow save 'anonymized' => // 1 for anonymous 'assessments' => // 1 for use assessments 'datestamp' => // 1 for use date stamps 'ipaddr' => // 1 for capture IP address 'radix' => // '.' for use period as decimal separator; ',' for use comma as decimal separator 'savetimings' => // "Y" if should save survey timings 'startlanguage' => // the starting language -- e.g. 'en' 'surveyls_dateformat' => // the index of the language specific date format -- e.g. 1 'tablename' => // the name of the table storing the survey data, if active -- e.g. lime_survey_38612 'target' => // the path for uploading files -- e.g. '/temp/files/' 'timeadjust' => // the time offset -- e.g. 0 'tempdir' => // the temporary directory for uploading files -- e.g. '/temp/' );

var

Type(s)

array

array of mappings of Question # (qid) to pipe-delimited list of SGQA codes used within it

qid2code :array
example

= "38612X11X150|38612X11X150other"

var

Type(s)

array

array of mappings of JavaScript Variable names to Question number (qid)

jsVar2qid :array
example

= '161'

var

Type(s)

array

maps name of the variable to the SGQ name (without the A suffix)

qcode2sgq :array
example

= "38612X10X147"

= "26626X37X705sq1#1"

var

Type(s)

array

array of mappings of knownVar aliases to the JavaScript variable names.

alias2varName :array

This maps both the SGQA and qcode alias names to the same 2 dimensional array

example

= array( 'jsName' => // the JavaScript variable name used by EM -- e.g. "java38612X11X147" 'jsPart' => // the JavaScript fragment used in EM's ____ array -- e.g. "'p1_sex':'java38612X11X147'" );

= array( 'jsName' => "java26626X37X705sq1#1" 'jsPart' => "'afDS_sq1_1':'java26626X37X705sq1#1'" );

var

Type(s)

array

JavaScript array of mappings of canonical JavaScript variable name to key attributes.

varNameAttr :array

These fragments are used to create the JavaScript varNameAttr array.

example

= "'java38612X11X147':{ 'jsName':'java38612X11X147','jsName_on':'java38612X11X147','sgqa':'38612X11X147','qid':147,'gid':11,'type':'G','default':'','rowdivid':'','onlynum':'','gseq':1,'answers':{ 'M':'Male','F':'Female'}}"

= "'java26626X37X705sq1#1':{ 'jsName':'java26626X37X705sq1#1','jsName_on':'java26626X37X705sq1#1','sgqa':'26626X37X705sq1#1','qid':705,'gid':37,'type':'1','default':'','rowdivid':'26626X37X705sq1','onlynum':'','gseq':1,'answers':{ '0~1':'1|Low','0~2':'2|Medium','0~3':'3|High','1~1':'1|Never','1~2':'2|Sometimes','1~3':'3|Always'}}"

var

Type(s)

array

array of enumerated answer lists indexed by qid These use a tilde syntax to indicate which scale the answer is part of.

qans :array
example

= "4|Child" // this means that code 4 in scale 0 has a coded value of 4 and a display value of 'Child'

[705]): ['1~2'] = '2|Sometimes' // this means that the second scale for this question uses the coded value of 2 to represent 'Sometimes'

TODO - add example from survey using assessments

var

Type(s)

array

map of gid to 0-based sequence number of groups

groupId2groupSeq :array
example

= 0 // means that the first group (gseq=0) has gid=10

var

Type(s)

array

map question # to an incremental count of question order across the whole survey

questionId2questionSeq :array
example

= 13 // means that that 14th question in the survey has qid=157

var

Type(s)

array

map question # to the group it is within, using an incremental count of group order

questionId2groupSeq :array
example

= 2 // means that qid 157 is in the 3rd page of questions (gseq = 2)

var

Type(s)

array

array of info about each Group, indexed by GroupSeq

groupSeqInfo :array
example

= array( 'qstart' => 9 // the first qseq within that group 'qend' => 13 //the last qseq within that group );

var

Type(s)

array

tracks which groups have at least one relevant, non-hidden question

gseq2relevanceStatus :array
example

= 0 // means that the third group (gseq==2) is currently irrelevant

var

Type(s)

array

maps question # to the validation equation(s) for that question.

qid2validationEqn :array

These are grouped by qid then validation type, such as 'value_range', and 'num_answers'

example

= array( 'eqn' => array( 'value_range' = "((is_empty(26626X34X703.NAOK) || 26626X34X703.NAOK >= (0)) and (is_empty(26626X34X703.NAOK) || 26626X34X703.NAOK <= (5)))" ), 'tips' => array( 'value_range' = "Each answer must be between {fixnum(0)} and {fixnum(5)}" ), 'subqValidEqns' = array( [] = array( 'subqValidSelector' => '' // 'subqValidEqn' => "(is_empty(26626X34X703.NAOK) || 26626X34X703.NAOK >= (0)) && (is_empty(26626X34X703.NAOK) || 26626X34X703.NAOK <= (5))" ), 'sumEqn' => '' // the equation to compute the current sum of the responses 'sumRemainingEqn' => '' // the equation to how much is left (for the question attribute that lets you specify the exact value of the sum of the answers) );

var

Type(s)

array

keeps relevance in proper sequence so can minimize relevance processing to see what should be see on page and in indexes Array is indexed on qseq

questionSeq2relevance :array
example

= array( 'relevance' => "!is_empty(num)" // the question-level relevance equation 'grelevance' => "" // the group-level relevance equation 'qid' => "699" // the question id 'qseq' => 3 // the 0-index question sequence 'gseq' => 0 // the 0-index group sequence 'jsResultVar_on' => 'answer26626X34X699' // the javascript variable holding the input value 'jsResultVar' => 'java26226X34X699' // the javascript variable (often hidden) holding the value to be submitted 'type' => 'N' // the one character question type 'hidden' => 0 // 1 if it should be always_hidden 'gid' => "34" // group id 'mandatory' => 'N' // 'Y' if mandatory, 'S' if soft mandatory 'eqn' => "" // TODO ?? 'help' => "" // the help text 'qtext' => "Enter a larger number than {num}" // the question text 'code' => 'afDS_sq5_1' // the full variable name 'other' => 'N' // whether the question supports the 'other' option - 'Y' if true 'rowdivid' => '2626X37X705sq5' // the javascript id for the row - in this case, the 5th subquestion 'aid' => 'sq5' // the answer id 'sqid' => '791' // the subquestion's qid (only populated for some question types) );

var

Type(s)

array

current Group sequence (0-based index)

currentGroupSeq :integer
example
var

Type(s)

integer

for Question-by-Question mode, the 0-based index

currentQuestionSeq :integer
example
var

Type(s)

integer

used in Question-by-Question mode

currentQID :integer
var

Type(s)

integer

set of the current set of questions to be displayed, indexed by QID - at least one must be relevant

currentQset :array|null

The array has N entries, where N is the number if qids in the Qset. Each has the following contents:

example

= array( 'info' => array() // this is an exact copy of $questionSeq2relevance[$qseq] -- TODO - remove redundancy 'relevant' => 1 // 1 if the question is currently relevant 'hidden' => 0 // 1 if the question is always hidden 'relEqn' => '' // the relevance equation -- TODO - how different from ['info']['relevance']? 'sgqa' => // pipe-separated list of SGQA codes for this question -- e.g. "26626X37X705sq1#0|26626X37X705sq1#1|26626X37X705sq2#0|26626X37X705sq2#1|26626X37X705sq3#0|26626X37X705sq3#1|26626X37X705sq4#0|26626X37X705sq4#1|26626X37X705sq5#0|26626X37X705sq5#1" 'unansweredSQs' => // pipe-separated list of currently unanswered SGQA codes for this question -- e.g. "26626X37X705sq1#0|26626X37X705sq1#1|26626X37X705sq3#0|26626X37X705sq3#1|26626X37X705sq5#0|26626X37X705sq5#1" 'valid' => 0 // 1 if the current answers pass all of the validation criteria for the question 'validEqn' => // the auto-generated validation criteria, based upon advanced question attributes -- e.g. "((count(if(count(26626X37X705sq1#0.NAOK,26626X37X705sq1#1.NAOK)==2,1,''), if(count(26626X37X705sq2#0.NAOK,26626X37X705sq2#1.NAOK)==2,1,''), if(count(26626X37X705sq3#0.NAOK,26626X37X705sq3#1.NAOK)==2,1,''), if(count(26626X37X705sq4#0.NAOK,26626X37X705sq4#1.NAOK)==2,1,''), if(count(26626X37X705sq5#0.NAOK,26626X37X705sq5#1.NAOK)==2,1,'')) >= (minSelect)) and (count(if(count(26626X37X705sq1#0.NAOK,26626X37X705sq1#1.NAOK)==2,1,''), if(count(26626X37X705sq2#0.NAOK,26626X37X705sq2#1.NAOK)==2,1,''), if(count(26626X37X705sq3#0.NAOK,26626X37X705sq3#1.NAOK)==2,1,''), if(count(26626X37X705sq4#0.NAOK,26626X37X705sq4#1.NAOK)==2,1,''), if(count(26626X37X705sq5#0.NAOK,26626X37X705sq5#1.NAOK)==2,1,'')) <= (maxSelect)))" 'prettyValidEqn' => // syntax-highlighted version of validEqn, only showing syntax errors 'validTip' => // html fragment to insert for the validation tip -- e.g. "

Please select between 1 and 3 answer(s)
" 'prettyValidTip' => // version of validTip that can be parsed by EM to create dynmamic validation -- e.g. "
Please select between {fixnum(minSelect)} and {fixnum(maxSelect)} answer(s)
" 'validJS' => // JavaScript fragment that can perform validation. This is the result of parsing validEqn -- e.g. "LEMif(LEManyNA('minSelect', 'maxSelect'),'',(((LEMcount(LEMif(LEMcount(LEMval('26626X37X705sq1#0.NAOK') , LEMval('26626X37X705sq1#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq2#0.NAOK') , LEMval('26626X37X705sq2#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq3#0.NAOK') , LEMval('26626X37X705sq3#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq4#0.NAOK') , LEMval('26626X37X705sq4#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq5#0.NAOK') , LEMval('26626X37X705sq5#1.NAOK') ) == 2, 1, '')) >= (LEMval('minSelect') )) && (LEMcount(LEMif(LEMcount(LEMval('26626X37X705sq1#0.NAOK') , LEMval('26626X37X705sq1#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq2#0.NAOK') , LEMval('26626X37X705sq2#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq3#0.NAOK') , LEMval('26626X37X705sq3#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq4#0.NAOK') , LEMval('26626X37X705sq4#1.NAOK') ) == 2, 1, ''), LEMif(LEMcount(LEMval('26626X37X705sq5#0.NAOK') , LEMval('26626X37X705sq5#1.NAOK') ) == 2, 1, '')) <= (LEMval('maxSelect') )))))" 'invalidSQs' => // current list of subquestions that fail validation criteria -- e.g. "26626X37X705sq1#0|26626X37X705sq1#1|26626X37X705sq2#0|26626X37X705sq2#1|26626X37X705sq3#0|26626X37X705sq3#1|26626X37X705sq4#0|26626X37X705sq4#1|26626X37X705sq5#0|26626X37X705sq5#1" 'relevantSQs' => // current list of subquestions that are relevant -- e.g. "26626X37X705sq1#0|26626X37X705sq1#1|26626X37X705sq2#0|26626X37X705sq2#1|26626X37X705sq3#0|26626X37X705sq3#1|26626X37X705sq4#0|26626X37X705sq4#1|26626X37X705sq5#0|26626X37X705sq5#1" 'irrelevantSQs' => // current list of subquestions that are irrelevant -- e.g. "26626X37X705sq2#0|26626X37X705sq2#1|26626X37X705sq4#0|26626X37X705sq4#1" 'subQrelEqn' => // TODO - ?? 'mandViolation' => 0 // 1 if the question is mandatory and fails the mandatory criteria 'anyUnanswered' => 1 // 1 if any parts of the question are unanswered 'mandTip' => '' // message to display if the question fails mandatory criteria 'message' => '' // TODO ?? 'updatedValues' => // array of values that should be updated for this question, as [$sgqa] = $value 'sumEqn' => '' // 'sumRemainingEqn' => '' // );

var

Type(s)

array|null

last result of NavigateForwards, NavigateBackwards, or JumpTo Array of status information about last movement, whether at question, group, or survey level

lastMoveResult :array|null
example

array( 'finished' => 0 // 1 if the survey has been completed and needs to be finalized 'message' => '' // any error message that needs to be displayed 'seq' => 1 // the sequence count, using gseq, or qseq units if in 'group' or 'question' mode, respectively 'mandViolation' => 0 // whether there was any violation of mandatory constraints in the last movement 'valid' => 0 // 1 if the last movement passed all validation constraints. 0 if there were any validation errors 'unansweredSQs' => // pipe-separated list of any subquestions that were not answered 'invalidSQs' => // pipe-separated list of any subquestions that failed validation constraints );

var

Type(s)

array|null

array of information needed to generate navigation index in question-by-question mode One entry for each question, indexed by qseq

indexQseq :array
example

= array( 'qid' => "700" // the question id 'qtext' => 'How old are you?' // the question text 'qcode' => 'age' // the variable name 'qhelp' => '' // the help text 'anyUnanswered' => 0 // 1 if there are any subquestions answered. Used for index display 'anyErrors' => 0 // 1 if there are any errors among the subquestions. Could be used for index display 'show' => 1 // 1 if there are any relevant, non-hidden subquestions. Only if so, then display the index entry 'gseq' => 0 // the group sequence 'gtext' => // text description for the group 'gname' => 'G1' // the group title 'gid' => "34" // the group id 'mandViolation' => 0 // 1 if the question as a whole fails the mandatory criteria 'valid' => 1 // 0 if any part of the question fails validation criteria. );

var

Type(s)

array

array of information needed to generate navigation index in group-by-group mode One entry for each group, indexed by gseq

indexGseq :array
example

= array( 'gtext' => // the description for the group 'gname' => 'G1' // the group title 'gid' => '34' // the group id 'anyUnanswered' => 0 // 1 if any questions within the group are unanswered 'anyErrors' => 0 // 1 if any of the questions within the group fail either validity or mandatory constraints 'valid' => 1 // 1 if at least question in the group is relevant and non-hidden 'mandViolation' => 0 // 1 if at least one relevant, non-hidden question in the group fails mandatory constraints 'show' => 1 // 1 if there is at least one relevant, non-hidden question within the group );

var

Type(s)

array

array of group sequence number to static info One entry per group, indexed on gseq

gseq2info :array
example

= array( 'group_order' => 0 // gseq 'gid' => "34" // group id 'group_name' => 'G2' // the group title 'description' => // the description of the group (e.g. gtitle) 'grelevance' => '' // the group-level relevance );

var

Type(s)

array

the maximum groupSeq reached - this is needed for Index

maxGroupSeq :integer
var

Type(s)

integer

the maximum Question reached sequencly ordered, used to show error to the user if we stop before this step with indexed survey.

maxQuestionSeq :integer

In question by question mode : $maxQuestionSeq==$SESSION['survey'.surveyid]['maxstep'], use it ?

var

Type(s)

integer

/** mapping of questions to information about their subquestions.

q2subqInfo :array

One entry per question, indexed on qid

example

= array( 'qid' => 702 // the question id 'qseq' => 6 // the question sequence 'gseq' => 0 // the group sequence 'sgqa' => '26626X34X702' // the root of the SGQA code (reallly just the SGQ) 'varName' => 'afSrcFilter_sq1' // the full qcode variable name - note, if there are subquestions, don't use this one. 'type' => 'M' // the one-letter question type 'fieldname' => '26626X34X702sq1' // the fieldname (used as JavaScript variable name, and also as database column name 'rootVarName' => 'afDS' // the root variable name 'preg' => '/[A-Z]+/' // regular expression validation equation, if any 'subqs' => array() of subquestions, where each contains: 'rowdivid' => '26626X34X702sq1' // the javascript id identifying the question row (so array_filter can hide rows) 'varName' => 'afSrcFilter_sq1' // the full variable name for the subquestion 'jsVarName_on' => 'java26626X34X702sq1' // the JavaScript variable name if the variable is defined on the current page 'jsVarName' => 'java26626X34X702sq1' // the JavaScript variable name to use if the variable is defined on a different page 'csuffix' => 'sq1' // the SGQ suffix to use for a fieldname 'sqsuffix' => '_sq1' // the suffix to use for a qcode variable name );

var

Type(s)

array

array of advanced question attributes for each question Indexed by qid; available for all quetions

qattr :array
example

= array( 'array_filter_exclude' => 'afSrcFilter' 'exclude_all_others' => 'sq5' 'max_answers' => '3' 'min_answers' => '1' 'other_replace_text' => '{afSrcFilter_other}' );

var

Type(s)

array

list of needed subquestion relevance (e.g. array_filter) Indexed by qid then sgqa; only generated for current group of questions

subQrelInfo :array
example

= array( 'qid' => '708' // the question id 'eqn' => "((26626X34X702sq2 != ''))" // the auto-generated subquestion-level relevance equation 'prettyPrintEqn' => '' // only generated if there errors - shows syntax highlighting of them 'result' => 0 // result of processing the subquestion-level relevance equation in the current context 'numJsVars' => 1 // the number of on-page javascript variables in 'eqn' 'relevancejs' => // the generated javascript from 'eqn' -- e.g. "LEMif(LEManyNA('26626X34X702sq2'),'',(((LEMval('26626X34X702sq2') != ""))))" 'relevanceVars' => "java26626X34X702sq2" // the pipe-separated list of on-page javascript variables in 'eqn' 'rowdivid' => "26626X37X708sq2" // the javascript id of the question row (so can apply array_filter) 'type' => 'array_filter' // semicolon delimited list of types of subquestion relevance filters applied 'qtype' => 'A' // the single character question type 'sgqa' => "26626X37X708" // the SGQ portion of the fieldname 'hasErrors' => 0 // 1 if there are any parse errors in the subquestion validation equations );

var

Type(s)

array

array of Group-level relevance status Indexed by gseq; only shows groups that have been visited

gRelInfo :array
example

= array( 'gseq' => 1 // group sequence 'eqn' => '' // the group-level relevance 'result' => 1 // result of processing the group-level relevance 'numJsVars' => 0 // the number of on-page javascript variables in the group-level relevance equation 'relevancejs' => '' // the javascript version of the relevance equation 'relevanceVars' => '' // the pipe-delimited list of on-page javascript variable names used within the group-level relevance equation 'prettyPrint' => '' // a pretty-print version of the group-level relevance equation, only if there are errors );

var

Type(s)

array

Array of timing information to debug how long it takes for portions of LEM to run.

runtimeTimings :array

Array of timing information (in seconds) for EM to help with debugging

example

= array( [0]="LimeExpressionManager::NavigateForwards" [1]=1.7079849243164 );

var

Type(s)

array

True (1) if calling LimeExpressionManager functions between StartSurvey and FinishProcessingPage Used (mostly deprecated) to detect calls to LEM which happen outside of the normal processing scope

initialized :boolean
var

Type(s)

boolean

True (1) if have already processed the relevance equations (so don't need to do it again)

processedRelevance :boolean
var

Type(s)

boolean

Message generated to show debug timing values, if debugLevel includes LEM_DEBUG_TIMING

debugTimingMsg :string
var

Type(s)

string

temporary variable to reduce need to parse same equation multiple times. Used for relevance and validation Array, indexed on equation, providing the following information:

ParseResultCache :array
example

= array( 'result' => 1 // result of processing the equation in the current scope 'prettyPrint' => '' // syntax-highlighted version of equation if there are any errors 'hasErrors' => 0 // 1 if there are any syntax errors );

var

Type(s)

array

array of 2nd scale answer lists for types ':' and ';' -- needed for convenient print of logic file Indexed on qid; available for all questions

multiflexiAnswers :array
example

= array( '1~1' => '1|Never', '1~2' => '2|Sometimes', '1~3' => '3|Always' );

var

Type(s)

array

used to specify whether to generate equations using SGQA codes or qcodes Default is to convert all qcode naming to sgqa naming when generating javascript, as that provides the greatest backwards compatibility TSV export of survey structure sets this to false so as to force use of qcode naming

sgqaNaming :Boolean
var

Type(s)

Boolean

Number of groups in survey (number of possible pages to display)

numGroups :integer
var

Type(s)

integer

Numer of questions in survey (counting display-only ones?)

numQuestions :integer
var

Type(s)

integer

String identifier for the active session

sessid :string
var

Type(s)

string

Linked list of array filters

qrootVarName2arrayFilter :array
var

Type(s)

array

Array, keyed on qid, to JavaScript and list of variables needed to implement exclude_all_others_auto

qid2exclusiveAuto :array
var

Type(s)

array

Array of invalid answer, key is sgq, value is the clear string to be shown Must be always unset after using (EM are in $_SESSION and never new .

invalidAnswerString :array<mixed,string>

...)

var

Type(s)

array<mixed,string>

Array of values to be updated

updatedValues :array
var

Type(s)

array