CRUDUI PHP API

Evaluator
in package

FinalYes

CRUDUI expression evaluator (expressions.md §5/§6/§7, JS PathResolver parity).

The shared 4-language fixture (tests/fixtures/expr/cases.json) is generated from the JS reference engine and is the §9 contract all four engines pass, so this evaluator mirrors validator-ts PathResolver function-for-function:

  • evaluate(node) → boolean (JS evaluateCondition): Boolean of the resolved value for Path/Literal; logical short-circuit; comparison; in; unary; a ternary is Boolean(its branch value).
  • evaluateValue(node) → value (JS evaluateExpressionValue): ternary returns its branch value; EVERYTHING else returns the boolean condition result.

truthy (JS Boolean): null/false/0/"" falsy; "0", "false", [], }, and every non-empty value truthy. == / != use JS loose equality (same-type ===, else numeric when both Number()-parse, else string). > >= < <= coerce BOTH sides to number (parseFloat, NaN→0) and compare numerically — there is no lexicographic branch (JS compare parity).

No eval / no regex evaluation (GRAMMAR §10) — pure AST walk.

Table of Contents

Properties

$currentPath  : array<string|int, mixed>
$formData  : array<string|int, mixed>|stdClass
$rowKeys  : array<string|int, mixed>

Methods

__construct()  : mixed
coerceNumber()  : float
Coerce a value to a number for comparison (JS coerceNumber): numbers pass through; a string is parseFloat-ed (NaN→0); booleans → 1/0; else 0.
evaluate()  : bool
Evaluate to a boolean condition result (JS evaluateCondition).
evaluateValue()  : mixed
Evaluate to a value (JS evaluateExpressionValue). A ternary returns its chosen branch's RAW value; every other node returns its boolean condition result (the shared fixture's `value` for non-ternary mirrors `truthy`).
isTruthy()  : bool
Truthy test (JS Boolean). null/false/0/0.0/"" are falsy; "0", "false", empty array, empty object, and every non-empty value are truthy.
looseEquals()  : bool
Loose equality (JS looseEquals). Values of one JS type compare as JSON values (jsonEquals); null equals only null; otherwise numeric equality when both Number()-parse, else string equality.
reference()  : mixed
The value of a field reference of a rule parameter (`equalTo`, `notEqual`, `enddate`): a relative path resolves as a relative expression path, a dotted name from the data root, and a bare name beside the current field.
compareOp()  : bool
evaluateBinary()  : bool
evaluateIn()  : bool
evaluateTernary()  : mixed
evaluateUnary()  : bool
getValueByPath()  : mixed
Read the value at a concrete path (JS getValueByPath). A missing key yields null. Numeric segments index into list arrays.
hasWildcard()  : bool
indexOfWildcard()  : int
inList()  : bool
isNumericSegment()  : bool
jsNumber()  : array{0: float, 1: bool}
JS Number(value) for equality: numbers pass; a string is numeric only when the WHOLE string parses (JS Number('12abc') is NaN); booleans → 1/0.
jsonEquals()  : bool
JSON-value structural equality (docs/spec/expressions.md, Evaluation): two lists hold equal elements in the same order, two objects the same keys with equal values in any key order; other values compare without conversion, numbers by value (int 1 equals float 1.0). A list never equals an object.
jsTypeOf()  : string
parseFloatPrefix()  : array{0: float, 1: bool}
parseFloat-style leading-number parse (JS parseFloat): reads an optional sign, digits, fraction, exponent prefix; returns failure when no number leads the string.
replaceWildcardWithIndex()  : array<int, string>
Replace each wildcard with the corresponding array index from currentPath, in order (JS replaceWildcardWithIndex). Wildcards with no matching index stay as '*' for later list resolution.
resolveOperand()  : array{0: mixed, 1: bool}
Resolve the left operand of a comparison: the list of candidate values of a wildcard path with true, or the one value of any other node with false.
resolvePath()  : mixed
resolvePathOperand()  : array{0: mixed, 1: bool}
The value of a path with false, or the list of candidate values of a wildcard that the current path does not resolve with true.
resolvePathSegments()  : array<int, string>
Compute the absolute path segments for a Path node (JS resolvePathSegments).
resolveTernaryBranchValue()  : mixed
Resolve a ternary branch to its RAW value (JS resolveTernaryBranchValue): nested ternary recurses; literal/path return their value; logical/in/ comparison/unary return their boolean.
resolveValue()  : mixed
Resolve a node to its raw value (JS resolveValue): Literal → its value; Path → the data at the resolved path (wildcards handled); Group → the inner condition's boolean.
resolveWildcardPath()  : array<int, array{path: list, value: mixed}>
Resolve a wildcard path to all concrete {path,value} pairs (JS resolveWildcardPath, ANY strategy across the array; object source skips the wildcard index per multiple:'only').
sameJsType()  : bool
Whether two values share the same JS typeof bucket (number covers int and float; arrays/objects are 'object').
toString()  : string

Properties

$currentPath read-only

private array<string|int, mixed> $currentPath = []

$formData read-only

private array<string|int, mixed>|stdClass $formData

$rowKeys read-only

private array<string|int, mixed> $rowKeys = []

Methods

__construct()

public __construct(array<string, mixed> $formData[, array<int, string> $currentPath = [] ][, array<int, int> $rowKeys = [] ]) : mixed
Parameters
$formData : array<string, mixed>

full form data tree (assoc arrays)

$currentPath : array<int, string> = []

path of the field carrying the condition, including the field name itself

$rowKeys : array<int, int> = []

positions of the row keys in $currentPath

coerceNumber()

Coerce a value to a number for comparison (JS coerceNumber): numbers pass through; a string is parseFloat-ed (NaN→0); booleans → 1/0; else 0.

public static coerceNumber(mixed $value) : float
Parameters
$value : mixed
Return values
float

evaluate()

Evaluate to a boolean condition result (JS evaluateCondition).

public evaluate(Node $node) : bool
Parameters
$node : Node
Return values
bool

evaluateValue()

Evaluate to a value (JS evaluateExpressionValue). A ternary returns its chosen branch's RAW value; every other node returns its boolean condition result (the shared fixture's `value` for non-ternary mirrors `truthy`).

public evaluateValue(Node $node) : mixed
Parameters
$node : Node

isTruthy()

Truthy test (JS Boolean). null/false/0/0.0/"" are falsy; "0", "false", empty array, empty object, and every non-empty value are truthy.

public static isTruthy(mixed $value) : bool
Parameters
$value : mixed
Return values
bool

looseEquals()

Loose equality (JS looseEquals). Values of one JS type compare as JSON values (jsonEquals); null equals only null; otherwise numeric equality when both Number()-parse, else string equality.

public static looseEquals(mixed $a, mixed $b) : bool
Parameters
$a : mixed
$b : mixed
Return values
bool

reference()

The value of a field reference of a rule parameter (`equalTo`, `notEqual`, `enddate`): a relative path resolves as a relative expression path, a dotted name from the data root, and a bare name beside the current field.

public reference(string $expression) : mixed
Parameters
$expression : string

compareOp()

private static compareOp(mixed $left, mixed $right, string $operator) : bool
Parameters
$left : mixed
$right : mixed
$operator : string
Return values
bool

getValueByPath()

Read the value at a concrete path (JS getValueByPath). A missing key yields null. Numeric segments index into list arrays.

private getValueByPath(array<int, string> $path) : mixed
Parameters
$path : array<int, string>

hasWildcard()

private static hasWildcard(array<int, string> $path) : bool
Parameters
$path : array<int, string>
Return values
bool

indexOfWildcard()

private static indexOfWildcard(array<int, string> $path) : int
Parameters
$path : array<int, string>
Return values
int

inList()

private static inList(mixed $value, array<int, mixed> $list) : bool
Parameters
$value : mixed
$list : array<int, mixed>
Return values
bool

isNumericSegment()

private static isNumericSegment(string $segment) : bool
Parameters
$segment : string
Return values
bool

jsNumber()

JS Number(value) for equality: numbers pass; a string is numeric only when the WHOLE string parses (JS Number('12abc') is NaN); booleans → 1/0.

private static jsNumber(mixed $value) : array{0: float, 1: bool}
Parameters
$value : mixed
Return values
array{0: float, 1: bool}

jsonEquals()

JSON-value structural equality (docs/spec/expressions.md, Evaluation): two lists hold equal elements in the same order, two objects the same keys with equal values in any key order; other values compare without conversion, numbers by value (int 1 equals float 1.0). A list never equals an object.

private static jsonEquals(mixed $a, mixed $b) : bool
Parameters
$a : mixed
$b : mixed
Return values
bool

jsTypeOf()

private static jsTypeOf(mixed $v) : string
Parameters
$v : mixed
Return values
string

parseFloatPrefix()

parseFloat-style leading-number parse (JS parseFloat): reads an optional sign, digits, fraction, exponent prefix; returns failure when no number leads the string.

private static parseFloatPrefix(string $value) : array{0: float, 1: bool}
Parameters
$value : string
Return values
array{0: float, 1: bool}

replaceWildcardWithIndex()

Replace each wildcard with the corresponding array index from currentPath, in order (JS replaceWildcardWithIndex). Wildcards with no matching index stay as '*' for later list resolution.

private static replaceWildcardWithIndex(array<int, string> $path, array<int, string> $currentPath) : array<int, string>
Parameters
$path : array<int, string>
$currentPath : array<int, string>
Return values
array<int, string>

resolveOperand()

Resolve the left operand of a comparison: the list of candidate values of a wildcard path with true, or the one value of any other node with false.

private resolveOperand(Node $node) : array{0: mixed, 1: bool}
Parameters
$node : Node
Return values
array{0: mixed, 1: bool}

resolvePathOperand()

The value of a path with false, or the list of candidate values of a wildcard that the current path does not resolve with true.

private resolvePathOperand(PathNode $node) : array{0: mixed, 1: bool}
Parameters
$node : PathNode
Return values
array{0: mixed, 1: bool}

resolvePathSegments()

Compute the absolute path segments for a Path node (JS resolvePathSegments).

private resolvePathSegments(PathNode $node) : array<int, string>
Parameters
$node : PathNode
Return values
array<int, string>

resolveTernaryBranchValue()

Resolve a ternary branch to its RAW value (JS resolveTernaryBranchValue): nested ternary recurses; literal/path return their value; logical/in/ comparison/unary return their boolean.

private resolveTernaryBranchValue(Node $node) : mixed
Parameters
$node : Node

resolveValue()

Resolve a node to its raw value (JS resolveValue): Literal → its value; Path → the data at the resolved path (wildcards handled); Group → the inner condition's boolean.

private resolveValue(Node $node) : mixed
Parameters
$node : Node

resolveWildcardPath()

Resolve a wildcard path to all concrete {path,value} pairs (JS resolveWildcardPath, ANY strategy across the array; object source skips the wildcard index per multiple:'only').

private resolveWildcardPath(array<int, string> $path) : array<int, array{path: list, value: mixed}>
Parameters
$path : array<int, string>
Return values
array<int, array{path: list, value: mixed}>

sameJsType()

Whether two values share the same JS typeof bucket (number covers int and float; arrays/objects are 'object').

private static sameJsType(mixed $a, mixed $b) : bool
Parameters
$a : mixed
$b : mixed
Return values
bool

toString()

private static toString(mixed $value) : string
Parameters
$value : mixed
Return values
string
On this page

Search results