@@ -515,20 +515,16 @@ component {
515515 */
516516 public boolean function $evaluateCondition () {
517517 local .rv = false ;
518- // since cf8 can't handle cfscript operators (==, != etc) inside an Evaluate() call we replace them with eq, neq etc in a try / catch
519518 local .evaluate = " condition,unless" ;
520519 local .iEnd = ListLen (local .evaluate );
521520 for (local .i = 1 ; local .i <= local .iEnd ; local .i ++ ) {
522521 local .item = ListGetAt (local .evaluate , local .i );
523522 if (StructKeyExists (arguments , local .item ) && Len (arguments [local .item ])) {
524523 local .key = local .item & " Evaluated" ;
525524 try {
526- local [local .key ] = Evaluate (arguments [local .item ]);
525+ local [local .key ] = EvaluateConditionString (arguments [local .item ]);
527526 } catch (any e ) {
528- // cfformat-ignore-start
529- arguments [local .item ] = Replace (ReplaceList (arguments [local .item ], " ==,!=,<,<=,>,>=" , " eq , neq , lt , lte , gt , gte " ), " " , " " , " all" );
530- // cfformat-ignore-end
531- local [local .key ] = Evaluate (arguments [local .item ]);
527+ return false ;
532528 }
533529 }
534530 }
@@ -755,4 +751,134 @@ component {
755751 }
756752 return local .rv ;
757753 }
754+
755+ /**
756+ * Function to evaluate a condition string without using Evaluate()
757+ * @condition The condition to resolve
758+ */
759+ public any function EvaluateConditionString (required string condition ) {
760+ // Replace CFScript operators with CFScript equivalents
761+ local .operatorList = " eq,neq,lt,lte,gt,gte" ;
762+ local .normalizedCondition = ReplaceList (condition , " ==,!=,<,<=,>,>=" , local .operatorList );
763+ local .normalizedCondition = Replace (local .normalizedCondition , " " , " " , " all" ); // Normalize spaces
764+ local .before = local .normalizedCondition ;
765+
766+ for (value in local .operatorList ){
767+ local .position = FindNoCase (value , local .normalizedCondition );
768+ if (local .position ){
769+ local .middle = value ;
770+ local .before = trim (Mid (local .normalizedCondition ,1 ,local .position - 1 ));
771+ local .after = trim (Mid (local .normalizedCondition , local .position + len (local .middle ), len (local .normalizedCondition )));
772+ }
773+ }
774+
775+ // Handle cases where the condition references `this`, logical comparisons, or function calls
776+ if (Left (local .before , 5 ) == " this." ) {
777+
778+ // Handle `this.someMethod()` or `this.someVariable`
779+ var key = Mid (local .before , 6 ); // Extract the part after "this."
780+ local .beforeRegexPattern = " ^(.*?)\(" ;
781+ local .beforeMatch = REFindNoCase (local .beforeRegexPattern , key , 1 , true );
782+
783+ if (local .beforeMatch .pos [1 ] > 0 ) {
784+ local .beforeParenthesis = Mid (key , 1 , local .beforeMatch .len [1 ] - 1 );
785+ local .afterParenthesis = Mid (key , local .beforeMatch .len [1 ] + 1 , len (key ));
786+ };
787+
788+ if (structKeyExists (local , ' afterParenthesis' )){
789+ local .afterRegexPattern = " ^(.*?)\)" ;
790+ local .afterMatch = REFindNoCase (local .afterRegexPattern , local .afterParenthesis , 1 , true );
791+ if (local .afterMatch .pos [1 ] > 0 ) {
792+ local .afterParenthesis = Mid (local .afterParenthesis , 1 , local .afterMatch .len [1 ] - 1 );
793+ }
794+
795+ if (structKeyExists (this , local .beforeParenthesis )){
796+
797+ if (IsCustomFunction (this [local .beforeParenthesis ])) {
798+ for (argString in local .afterParenthesis ) {
799+ // Split the string on "="
800+ local .splitArg = ListToArray (argString , " =" );
801+ local .variableName = Trim (local .splitArg [1 ]); // Left-hand side (variable name)
802+ local .variableValue = Replace (local .splitArg [2 ], " '" , " " , " all" ); // Right-hand side (value without quotes)
803+
804+ // Add to the arguments collection
805+ local .argumentsCollection [local .variableName ] = local .variableValue ;
806+ }
807+ local .rv = this [local .beforeParenthesis ](argumentCollection = local .argumentsCollection ); // Call the function
808+ } else {
809+ local .rv = this [local .beforeParenthesis ]; // Return the variable value
810+ }
811+ }
812+ }
813+
814+ if (StructKeyExists (this , key )) {
815+ if (IsCustomFunction (this [key ])) {
816+ local .rv = this [key ](); // Call the function
817+ } else {
818+ local .rv = this [key ]; // Return the variable value
819+ }
820+ }
821+
822+ } else if (right (local .normalizedCondition , 2 ) eq ' ()' ){
823+ if (find (" !" , local .normalizedCondition )){
824+ local .normalizedCondition = replace (local .normalizedCondition , " !" , " " , " one" );
825+ return ! this [replace (local .normalizedCondition , ' ()' , ' ' )]();
826+ } else {
827+ return this [replace (local .normalizedCondition , ' ()' , ' ' )]();
828+ }
829+ } else {
830+ // Handle logical expressions (e.g., "1 eq 0", "5 gt 3", "myFunction() eq true")
831+ local .tokens = ListToArray (local .normalizedCondition , " " );
832+ if (ArrayLen (local .tokens ) < 3 ) {
833+ return false ; // Invalid condition
834+ }
835+
836+ local .leftOperand = local .tokens [1 ];
837+ local .operator = local .tokens [2 ];
838+ local .rightOperand = local .tokens [3 ];
839+
840+ // Resolve variables or cast to numeric values
841+ local .leftOperand = isNumeric (local .leftOperand ) ? JavaCast (" double" , local .leftOperand ) : local .leftOperand ;
842+ local .rightOperand = isNumeric (local .rightOperand ) ? JavaCast (" double" , local .rightOperand ) : local .rightOperand ;
843+ // Evaluate the logical expression
844+ return resolveOperator (local .leftOperand , local .rightOperand , local .operator );
845+ }
846+
847+ if (structKeyExists (local , ' after' ) && structKeyExists (local , ' middle' )){
848+ local .singleRegexPattern = " ^'.*'$" ;
849+ local .doubleRegexPattern = ' ^".*"$' ;
850+ if (REFindNoCase (local .singleRegexPattern , local .after )) {
851+ local .after = Replace (local .after , " '" , " " , " all" );
852+ }
853+ if (REFindNoCase (local .doubleRegexPattern , local .after )) {
854+ local .after = Replace (local .after , ' "' , " " , " all" );
855+ }
856+
857+ return resolveOperator (local .rv , local .after , local .middle );
858+ }
859+
860+ return structKeyExists (local , rv )? local .rv : false ;
861+ }
862+
863+ /**
864+ * Evaluate a logical expression based on the operator.
865+ */
866+ public boolean function resolveOperator (required any firstOperator , required any secondOperator , required any operator ){
867+ switch (arguments .operator ) {
868+ case " eq" :
869+ return (arguments .firstOperator == arguments .secondOperator );
870+ case " neq" :
871+ return (arguments .firstOperator ! = arguments .secondOperator );
872+ case " lt" :
873+ return (arguments .firstOperator < arguments .secondOperator );
874+ case " lte" :
875+ return (arguments .firstOperator <= arguments .secondOperator );
876+ case " gt" :
877+ return (arguments .firstOperator > arguments .secondOperator );
878+ case " gte" :
879+ return (arguments .firstOperator >= arguments .secondOperator );
880+ default :
881+ throw (" Unsupported operator in condition: " & arguments .operator );
882+ }
883+ }
758884}
0 commit comments