PluginProbe
WowAddons – Product Addons and Product Options With Custom Fields / trunk
WowAddons – Product Addons and Product Options With Custom Fields vtrunk
1.7.2 1.7.1 1.7.0 1.6.21 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.5.10 1.5.11 1.5.2 1.5.3 1.5.4 1.5.5 All 57 releases
product-addons / includes / common / formula / ast / class-expression-function-node.php

class-expression-function-node.php in WowAddons – Product Addons and Product Options With Custom Fields trunk, at includes/common/formula/ast/class-expression-function-node.php

136 lines 4.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore
2 /**
3 * Function call node (if/abs/ceil/floor/max/min/pow/round).
4 *
5 * @package PRAD
6 * @since 1.5.8
7 */
8
9 namespace PRAD\Includes\Common\Formula\Ast;
10
11 use PRAD\Includes\Common\Formula\Abstract_Expression_Engine;
12 use PRAD\Includes\Common\Formula\Expression_Exception;
13
14 defined( 'ABSPATH' ) || exit;
15
16 /**
17 * Represents a function call node in the expression AST.
18 *
19 * Handles evaluation of supported functions such as if, abs, ceil, floor, max, min, pow, and round.
20 *
21 * @package PRAD
22 * @since 1.5.8
23 */
24 final class Expression_Function_Node implements Expression_Node {
25 /**
26 * Function name.
27 *
28 * @var string
29 */
30 private $name;
31 /**
32 * Argument nodes.
33 *
34 * @var Expression_Node[]
35 */
36 private $args;
37 /**
38 * Token position.
39 *
40 * @var int
41 */
42 private $pos;
43
44 /**
45 * Constructs a new Expression_Function_Node instance.
46 *
47 * @param string $name Function name.
48 * @param Expression_Node[] $args Argument nodes.
49 * @param int $pos Token position.
50 */
51 public function __construct( $name, array $args, $pos ) {
52 $this->name = strtolower( (string) $name );
53 $this->args = $args;
54 $this->pos = (int) $pos;
55 }
56
57 /**
58 * Evaluates the function node using the provided expression engine and context.
59 *
60 * @param Abstract_Expression_Engine $engine The expression engine to use for evaluation.
61 * @param array $context Optional context for evaluation.
62 * @return mixed The result of the function evaluation.
63 * @throws Expression_Exception If the function arguments are invalid or unknown function is called.
64 */
65 public function evaluate( Abstract_Expression_Engine $engine, array $context = array() ) {
66 $name = $this->name;
67
68 // Lazy evaluation for IF.
69 if ( 'if' === $name ) {
70 if ( 3 !== count( $this->args ) ) {
71 throw new Expression_Exception( 'if() expects 3 arguments.' );
72 }
73 $condition = $engine->to_bool( $this->args[0]->evaluate( $engine, $context ) );
74 return $condition ? $this->args[1]->evaluate( $engine, $context ) : $this->args[2]->evaluate( $engine, $context );
75 }
76
77 $evaluated = array();
78 foreach ( $this->args as $arg ) {
79 $evaluated[] = $arg->evaluate( $engine, $context );
80 }
81
82 if ( 'abs' === $name ) {
83 if ( 1 !== count( $evaluated ) ) {
84 throw new Expression_Exception( 'abs() expects 1 argument.' );
85 }
86 return abs( $engine->to_number( $evaluated[0] ) );
87 }
88 if ( 'ceil' === $name ) {
89 if ( 1 !== count( $evaluated ) ) {
90 throw new Expression_Exception( 'ceil() expects 1 argument.' );
91 }
92 return ceil( $engine->to_number( $evaluated[0] ) );
93 }
94 if ( 'floor' === $name ) {
95 if ( 1 !== count( $evaluated ) ) {
96 throw new Expression_Exception( 'floor() expects 1 argument.' );
97 }
98 return floor( $engine->to_number( $evaluated[0] ) );
99 }
100 if ( 'round' === $name ) {
101 $argc = count( $evaluated );
102 if ( $argc < 1 || $argc > 2 ) {
103 throw new Expression_Exception( 'round() expects 1 or 2 arguments.' );
104 }
105 $value = $engine->to_number( $evaluated[0] );
106 $precision = ( 2 === $argc ) ? (int) $engine->to_number( $evaluated[1] ) : 0;
107 // Match PHP's default rounding mode (PHP_ROUND_HALF_UP) explicitly.
108 return round( $value, $precision, PHP_ROUND_HALF_UP );
109 }
110 if ( 'pow' === $name ) {
111 if ( 2 !== count( $evaluated ) ) {
112 throw new Expression_Exception( 'pow() expects 2 arguments.' );
113 }
114 return pow( $engine->to_number( $evaluated[0] ), $engine->to_number( $evaluated[1] ) );
115 }
116 if ( 'min' === $name ) {
117 if ( count( $evaluated ) < 1 ) {
118 throw new Expression_Exception( 'min() expects at least 1 argument.' );
119 }
120 $nums = array_map( array( $engine, 'to_number' ), $evaluated );
121 return min( $nums );
122 }
123 if ( 'max' === $name ) {
124 if ( count( $evaluated ) < 1 ) {
125 throw new Expression_Exception( 'max() expects at least 1 argument.' );
126 }
127 $nums = array_map( array( $engine, 'to_number' ), $evaluated );
128 return max( $nums );
129 }
130
131 throw new Expression_Exception(
132 'Unknown function "' . esc_html( $this->name ) . '" at position ' . esc_html( $this->pos )
133 );
134 }
135 }
136