ExpressionManager

Description of ExpressionManager (1) Does safe evaluation of PHP expressions. Only registered Functions, and known Variables are allowed.

(a) Functions include any math, string processing, conditional, formatting, etc. functions (2) This class replaces LimeSurvey's <= 1.91+ process of resolving strings that contain LimeReplacementFields (a) String is split by expressions (by curly braces, but safely supporting strings and escaped curly braces) (b) Expressions (things surrounded by curly braces) are evaluated - thereby doing LimeReplacementField substitution and/or more complex calculations (c) Non-expressions are left intact (d) The array of stringParts are re-joined to create the desired final string. (3) The core of ExpressionScript Engine is a Recursive Descent Parser (RDP), based off of one build via JavaCC by TMSWhite in 1999. (a) Functions that start with RDP_ should not be touched unless you really understand compiler design.

author

LimeSurvey Team (limesurvey.org)

author

Thomas M. White (TMSWhite)

package

Default

Methods

__construct

__construct()

Add a package for expression

addPackageForExpressionManager(string $name,array $definition): void

Arguments

$name

string

of package

Add extra attributes for var

addRegexpExtraAttributes(array<mixed,string> $extraAttributes,boolean $static = true): void

Arguments

$extraAttributes

array<mixed,string>

$static

boolean

is a static attribute , unused currently since there are no way to create the EM js system

Split a source string into STRING vs. EXPRESSION, where the latter is surrounded by unescaped curly braces.

asSplitStringOnExpressions(string $src): array

This version properly handles nested curly braces and curly braces within strings within curly braces - both of which are needed to better support JavaScript Users still need to add a space or carriage return after opening braces (and ideally before closing braces too) to avoid having them treated as expressions.

Arguments

$src

string

Response

array

Clear cache of tailoring content.

ClearSubstitutionInfo()

When re-displaying same page, need to avoid generating double the amount of tailoring content.

If the equation contains reference to this, expand to comma separated list if needed.

ExpandThisVar(string $src): string

Arguments

$src

string

Response

string

Since this class can be get by session, need to add a call the «start» event manually

ExpressionManagerStartEvent(): void

Flatten out an array, keeping it in the proper order

flatten_array(array $a): array

Arguments

$a

array

Response

array

Returns array of all JavaScript-equivalent variable names used when parsing a string via sProcessStringContainingExpressions

GetAllJsVarsUsed(): array

Response

array

Show a table of allowable ExpressionScript Engine functions

GetAllowableFunctions(): string
static

Response

string

Returns array of all variables used when parsing a string via sProcessStringContainingExpressions

GetAllVarsUsed(): array

Response

array

Get info about all <span> elements needed for dynamic tailoring

GetCurrentSubstitutionInfo(): array

Response

array

Return an array of errors

GetErrors(): array

Response

array

Converts the most recent expression into a valid JavaScript expression, mapping function and variable names and operators as needed.

GetJavaScriptEquivalentOfExpression(): string

Response

string

the JavaScript expresssion

Generate the function needed to dynamically change the value of a <span> section

GetJavaScriptFunctionForReplacement(integer $questionNum,string $elementId,string $eqn): string

Arguments

$questionNum

integer

No longer used

$elementId

string

  • the ID name for the function

$eqn

string

No longer used

Response

string

: javascript part

JavaScript Test function - simply writes the result of the current JavaScriptEquivalentFunction to the output buffer.

GetJavascriptTestforExpression(string $expected,integer $num): string

Arguments

$expected

string

$num

integer

Response

string

Return the JavaScript variable name for a named variable

GetJsVarFor(string $name): string

Arguments

$name

string

Response

string

Return the list of all of the JavaScript variables used by the most recent expression

GetJsVarsUsed(): array

Response

array

Returns the most recent PrettyPrint string generated by sProcessStringContainingExpressions

GetLastPrettyPrintExpression()

Get informatin about type mismatch between arguments.

getMismatchInformation(\Token $arg1,\Token $arg2): array<mixed,boolean>

Arguments

$arg1

\Token

$arg2

\Token

Response

array<mixed,boolean>

Like (boolean $bMismatchType, boolean $bBothNumeric, boolean $bBothString)

Return the list of all of the JavaScript variables used by the most recent expression - only those that are set on the current page This is used to control static vs dynamic substitution. If an expression is entirely made up of off-page changes, it can be statically replaced.

GetOnPageJsVarsUsed(): array

Response

array

Color-codes Expressions (using HTML <span> tags), showing variable types and values.

GetPrettyPrintString(): string

Response

string

HTML

getRegexpStaticValidAttributes

getRegexpStaticValidAttributes()

getRegexpValidAttributes

getRegexpValidAttributes()

Return the result of evaluating the equation - NULL if error

GetResult(): mixed

Response

mixed

Get information about the variable, including JavaScript name, read-write status, and whether set on current page.

GetVarAttribute(string $name,string|null $attr,string $default): string

Arguments

$name

string

$attr

string|null

$default

string

Response

string

Return array of the list of variables used in the equation

GetVarsUsed(): array

Response

array

Return array of warnings

GetWarnings(): array

Response

array

Show a translated string for admin user, always in admin language #12208 public for geterrors_exprmgr_regexMatch function only

gT(string $string,string $sEscapeMode = 'html'): string
static

Arguments

$string

string

to translate

$sEscapeMode

string

Valid values are html (this is the default, js and unescaped)

Response

string

: translated string

Return true if there were syntax or processing errors

HasErrors(): boolean

Response

boolean

Return true if there are syntax errors

HasSyntaxErrors(): boolean

Response

boolean

Process an expression and return its boolean value

ProcessBooleanExpression(string $expr,integer $groupSeq = -1,integer $questionSeq = -1): boolean

Arguments

$expr

string

$groupSeq

integer

  • needed to determine whether using variables before they are declared

$questionSeq

integer

  • needed to determine whether using variables before they are declared

Response

boolean

Add an error to the error log

RDP_AddError(string $errMsg,array|null $token): void

Arguments

$errMsg

string

$token

array|null

Add a warning to the error log

RDP_AddWarning(\EMWarningInterface $warning): void

Arguments

Main entry function

RDP_Evaluate(string $expr,boolean $onlyparse = false,boolean $resetErrorsAndWarnings = true): boolean

Arguments

$expr

string

$onlyparse

boolean

  • if true, then validate the syntax without computing an answer

$resetErrorsAndWarnings

boolean

  • if true (default), EM errors and warnings will be cleared before evaluation

Response

boolean

  • true if success, false if any error occurred

Process "a op b" where op in (+,-,concatenate)

RDP_EvaluateAdditiveExpression(): boolean

Response

boolean

  • true if success, false if any error occurred

RDP_EvaluateBinary() computes binary expressions, such as (a or b), (c * d), popping the top two entries off the stack and pushing the result back onto the stack.

RDP_EvaluateBinary(array $token): boolean

Arguments

$token

array

Response

boolean

  • false if there is any error, else true

Process a Constant (number of string), retrieve the value of a known variable, or process a function, returning result on the stack.

RDP_EvaluateConstantVarOrFunction(): boolean|null

Response

boolean|null

  • true if success, false if any error occurred

Process "a == b", "a eq b", "a != b", "a ne b"

RDP_EvaluateEqualityExpression(): boolean

Response

boolean

  • true if success, false if any error occurred

Process a single expression (e.g. without commas)

RDP_EvaluateExpression(): boolean

Response

boolean

  • true if success, false if any error occurred

Process "expression [, expression]*

RDP_EvaluateExpressions(): boolean

Response

boolean

  • true if success, false if any error occurred

Process a function call

RDP_EvaluateFunction(): boolean|null

Response

boolean|null

  • true if success, false if any error occurred

Process "a && b" or "a and b"

RDP_EvaluateLogicalAndExpression(): boolean

Response

boolean

  • true if success, false if any error occurred

Process "a || b" or "a or b"

RDP_EvaluateLogicalOrExpression(): boolean

Response

boolean

  • true if success, false if any error occurred

Process "a op b" where op in (*,/)

RDP_EvaluateMultiplicativeExpression(): boolean

Response

boolean

  • true if success, false if any error occurred

Process expressions including functions and parenthesized blocks

RDP_EvaluatePrimaryExpression(): boolean|null

Response

boolean|null

  • true if success, false if any error occurred

Process "a op b" where op in (lt, gt, le, ge, <, >, <=, >=)

RDP_EvaluateRelationExpression(): boolean

Response

boolean

  • true if success, false if any error occurred

Processes operations like +a, -b, !c

RDP_EvaluateUnary(array $token): boolean

Arguments

$token

array

Response

boolean

  • true if success, false if any error occurred

Process "op a" where op in (+,-,!)

RDP_EvaluateUnaryExpression(): boolean|null

Response

boolean|null

  • true if success, false if any error occurred

RDP_GetErrors

RDP_GetErrors(): array

Response

array

Return true if the function name is registered

RDP_isValidFunction(string $name): boolean

Arguments

$name

string

Response

boolean

Return true if the variable name is registered

RDP_isValidVariable(string $name): boolean

Arguments

$name

string

Response

boolean

Return true if the variable name is writable

RDP_isWritableVariable(string $name): boolean

Arguments

$name

string

Response

boolean

Run a registered function Some PHP functions require specific data types - those can be cast here.

RDP_RunFunction(array $funcNameToken,array $params): boolean|null

Arguments

$funcNameToken

array

$params

array

Response

boolean|null

Set the value of a registered variable

RDP_SetVariableValue(string $op,string $name,string $value): integer

Arguments

$op

string

  • the operator (=,*=,/=,+=,-=)

$name

string

$value

string

Response

integer

Pop a value token off of the stack

RDP_StackPop(): \token

Response

\token

Stack only holds values (number, string), not operators

RDP_StackPush(array $token)

Arguments

$token

array

Split the source string into tokens, removing whitespace, and categorizing them by type.

RDP_Tokenize(string $sSource,boolean $bOnEdit = false): array

Arguments

$sSource

string

: the string to tokenize

$bOnEdit

boolean

: on edition, actually don't remove space

Response

array

Add user functions to array of allowable functions within the equation.

RegisterFunctions(array $functions)

$functions is an array of key to value mappings like this: See $this->RDP_ValidFunctions for examples of the syntax

Arguments

$functions

array

Reset current errors

ResetErrors(): void
see \Related

issue #16738: https://bugs.limesurvey.org/view.php?id=16738

link

ProcessBooleanExpression didn't reset RDP_errors anb RDP_warnings, need a way to reset for Survey logic checking

Reset current errors and current warnings

ResetErrorsAndWarnings(): void

Reset current warnings

ResetWarnings(): void
see \Related

issue #15547: Invalid error count on Survey Logic file for subquestion relevance

link

ProcessBooleanExpression didn't reset RDP_errors anb RDP_warnings, need a way to reset for Survey logic checking

SetJsVarsUsed

SetJsVarsUsed( $vars): void

Arguments

$vars

This is only used when there are no needed substitutions

SetPrettyPrintSource(string $expr)

Arguments

$expr

string

Specify the survey mode for this survey. Options are 'survey', 'group', and 'question'

SetSurveyMode(string $mode)

Arguments

$mode

string

Show a table of allowable ExpressionScript Engine functions

ShowAllowableFunctions(): string
static

Response

string

Process multiple substitution iterations of a full string, containing multiple expressions delimited by {}, return a consolidated string

sProcessStringContainingExpressions(string $src,integer $questionNum,integer $numRecursionLevels = 1,integer $whichPrettyPrintIteration = 1,integer $groupSeq = -1,integer $questionSeq = -1,boolean $staticReplacement = false): string

Arguments

$src

string

$questionNum

integer

$numRecursionLevels

integer

  • number of levels of recursive substitution to perform

$whichPrettyPrintIteration

integer

  • if recursing, specify which pretty-print iteration is desired

$groupSeq

integer

  • needed to determine whether using variables before they are declared

$questionSeq

integer

  • needed to determine whether using variables before they are declared

$staticReplacement

boolean

Response

string

Process one substitution iteration of a full string, containing multiple expressions delimited by {}, return a consolidated string

sProcessStringContainingExpressionsHelper(string $src,integer $questionNum,boolean $staticReplacement = false): string

Arguments

$src

string

$questionNum

integer

  • used to generate substitution s that indicate to which question they belong

$staticReplacement

boolean

Response

string

Start processing a group of substitions - will be incrementally numbered

StartProcessingGroup( $sid = null, $rooturl = '', $hyperlinkSyntaxHighlighting = true)

Arguments

$sid

$rooturl

$hyperlinkSyntaxHighlighting

Public call of RDP_Tokenize

Tokenize(string $sSource,boolean $bOnEdit): array

Arguments

$sSource

string

: the string to tokenize

$bOnEdit

boolean

: on edition, actually don't remove space

Response

array

Properties

aRDP_regexpVariableAttribute

aRDP_regexpVariableAttribute :

Type(s)

aRDP_regexpStaticAttribute

aRDP_regexpStaticAttribute :

Type(s)

RDP_ExpressionRegex

RDP_ExpressionRegex :

Type(s)

RDP_TokenType

RDP_TokenType :

Type(s)

RDP_TokenizerRegex

RDP_TokenizerRegex :

Type(s)

RDP_CategorizeTokensRegex

RDP_CategorizeTokensRegex :

Type(s)

RDP_ValidFunctions

RDP_ValidFunctions :

Type(s)

RDP_expr

RDP_expr :

Type(s)

RDP_tokens

RDP_tokens :

Type(s)

RDP_count

RDP_count :

Type(s)

RDP_pos

RDP_pos :

Type(s)

information about current errors : array with string, $token (EM internal array). Reset in RDP_Evaluate (and only in RDP_Evaluate)

RDP_errs :array<mixed,array>
var

information about current errors : array with string, $token (EM internal array). Reset in RDP_Evaluate (and only in RDP_Evaluate)

Type(s)

array<mixed,array>

information about current warnings : array with string, $token (EM internal array) and optional link Reset in RDP_Evaluate or manually

RDP_warnings :array<mixed,array>
var

information about current warnings : array with string, $token (EM internal array) and optional link Reset in RDP_Evaluate or manually

Type(s)

array<mixed,array>

RDP_onlyparse

RDP_onlyparse :

Type(s)

RDP_stack

RDP_stack :

Type(s)

RDP_result

RDP_result :

Type(s)

RDP_evalStatus

RDP_evalStatus :

Type(s)

varsUsed

varsUsed :

Type(s)

resetErrorsAndWarningsOnEachPart

resetErrorsAndWarningsOnEachPart :

Type(s)

allVarsUsed

allVarsUsed :

Type(s)

prettyPrintSource

prettyPrintSource :

Type(s)

substitutionNum

substitutionNum :

Type(s)

substitutionInfo

substitutionInfo :array
var

Type(s)

array

jsExpression

jsExpression :

Type(s)

questionSeq

questionSeq :

Type(s)

groupSeq

groupSeq :

Type(s)

surveyMode

surveyMode :

Type(s)

sid

sid :

Type(s)

hyperlinkSyntaxHighlighting

hyperlinkSyntaxHighlighting :

Type(s)

sgqaNaming

sgqaNaming :

Type(s)