| @@ -2,13 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | namespace BitCode\BitForm\Core\WorkFlow; |
| 4 | 4 | |
| 5 | 5 | use BitCode\BitForm\Core\Integration\IntegrationHandler; |
| 6 | -use BitCode\BitForm\Core\Messages\EmailTemplateHandler; | |
| 7 | 6 | use BitCode\BitForm\Core\Messages\SuccessMessageHandler; |
| 8 | 7 | use BitCode\BitForm\Core\Util\FieldValueHandler; |
| 9 | 8 | use BitCode\BitForm\Core\Util\SmartTags; |
| 10 | -use BitCode\BitForm\Core\Util\Utilities; | |
| 11 | 9 | |
| 12 | 10 | final class Helper |
| 13 | 11 | { |
| 14 | 12 | public static function getFieldData($fields) |
| @@ -15,12 +13,11 @@ | ||
| 15 | 13 | { |
| 16 | 14 | $fieldData = []; |
| 17 | 15 | |
| 18 | 16 | foreach ($fields as $fieldKey => $fieldDetail) { |
| 19 | - $value = isset($fieldDetail->val) ? $fieldDetail->val : (isset($fieldDetail->defaultValue) ? $fieldDetail->defaultValue : ''); | |
| 20 | 17 | $fieldData[$fieldKey] = [ |
| 21 | 18 | 'key' => $fieldKey, |
| 22 | - 'value' => $value, | |
| 19 | + 'value' => empty($fieldDetail->val) ? '' : $fieldDetail->val, | |
| 23 | 20 | 'type' => $fieldDetail->typ, |
| 24 | 21 | ]; |
| 25 | 22 | if (isset($fieldDetail->mul)) { |
| 26 | 23 | $fieldData[$fieldKey] = |
| @@ -57,11 +54,11 @@ | ||
| 57 | 54 | } |
| 58 | 55 | return $fieldData; |
| 59 | 56 | } |
| 60 | 57 | |
| 61 | - public static function replaceFieldWithValue($stringToReplaceField, $fieldValues, $evalMathExpr = true, $formID = null, $stripShortcodesFromValues = false) | |
| 58 | + public static function replaceFieldWithValue($stringToReplaceField, $fieldValues, $evalMathExpr = true) | |
| 62 | 59 | { |
| 63 | - $stringToReplaceField = FieldValueHandler::replaceFieldWithValue($stringToReplaceField, $fieldValues, $formID, $stripShortcodesFromValues); | |
| 60 | + $stringToReplaceField = FieldValueHandler::replaceFieldWithValue($stringToReplaceField, $fieldValues); | |
| 64 | 61 | if ($evalMathExpr) { |
| 65 | 62 | return self::evalMathExpression($stringToReplaceField); |
| 66 | 63 | } |
| 67 | 64 | return $stringToReplaceField; |
| @@ -66,60 +63,42 @@ | ||
| 66 | 63 | } |
| 67 | 64 | return $stringToReplaceField; |
| 68 | 65 | } |
| 69 | 66 | |
| 70 | - public static function setDefaultSubmitConfirmation($confirmationType, $fieldValue, $formId, $logID = 0, $workFlowRun = null) | |
| 67 | + public static function setDefaultSubmitConfirmation($confirmationType, $fieldValue, $formId, $logID = 0) | |
| 71 | 68 | { |
| 72 | 69 | $messageId = 0; |
| 73 | 70 | $returnableData = null; |
| 74 | - $afterSubmit = null; | |
| 75 | - $msgDuration = null; | |
| 71 | + return [ | |
| 72 | + 'msg_id' => $messageId, | |
| 73 | + 'confirmation' => $returnableData, | |
| 74 | + ]; | |
| 76 | 75 | $integrationHandler = new IntegrationHandler($formId); |
| 77 | - $conditionalActionIds = self::getDefaultSubmitExcludedActionIds($formId, $workFlowRun); | |
| 78 | 76 | switch ($confirmationType) { |
| 79 | 77 | case 'successMsg': |
| 80 | - // Standalone confirmation: show the first ENABLED success message without requiring a workflow. | |
| 81 | - $successMessageHandler = new SuccessMessageHandler($formId); | |
| 78 | + $successMessageHandler | |
| 79 | + = new SuccessMessageHandler($formId); | |
| 82 | 80 | $successMessage = $successMessageHandler->getAllMessage(); |
| 83 | - if (!is_wp_error($successMessage) && !empty($successMessage)) { | |
| 84 | - foreach ($successMessage as $msg) { | |
| 85 | - $msgConfig = Utilities::jsonObj($msg->message_config); | |
| 86 | - if ( | |
| 87 | - isset($msgConfig->status) && empty($msgConfig->status) | |
| 88 | - || isset($conditionalActionIds['successMsg'][(string) $msg->id]) | |
| 89 | - ) { | |
| 90 | - continue; | |
| 91 | - } | |
| 92 | - $returnableData = self::replaceFieldWithValue($msg->message_content, $fieldValue, true, null, true); | |
| 93 | - $messageId = $msg->id; | |
| 94 | - if (isset($msgConfig->afterSubmit)) { | |
| 95 | - $afterSubmit = $msgConfig->afterSubmit; | |
| 96 | - } | |
| 97 | - if (!empty($msgConfig->autoHide)) { | |
| 98 | - $msgDuration = abs(floatval($msgConfig->duration ?? 0) * 1000); | |
| 99 | - } | |
| 100 | - break; | |
| 101 | - } | |
| 81 | + if (!is_wp_error($successMessage) && !empty($successMessage) && count($successMessage) > 0) { | |
| 82 | + $returnableData = self::replaceFieldWithValue($successMessage[0]->message_content, $fieldValue); | |
| 83 | + $messageId = $successMessage[0]->id; | |
| 102 | 84 | } |
| 103 | 85 | break; |
| 104 | 86 | case 'redirectPage': |
| 105 | - $redirectPages = $integrationHandler->getAllIntegration('form', 'redirectPage', 1); | |
| 106 | - if (!is_wp_error($redirectPages) && !empty($redirectPages)) { | |
| 107 | - foreach ($redirectPages as $redirectPage) { | |
| 108 | - if (isset($conditionalActionIds['redirectPage'][(string) $redirectPage->id])) { | |
| 109 | - continue; | |
| 110 | - } | |
| 111 | - $url = Utilities::jsonObj($redirectPage->integration_details ?? '')->url ?? ''; | |
| 112 | - if (!empty($url)) { | |
| 113 | - $url = self::replaceFieldWithValue($url, $fieldValue); | |
| 114 | - } | |
| 115 | - $returnableData = empty($url) ? '' : esc_url_raw($url); | |
| 116 | - break; | |
| 87 | + $redirectPage = $integrationHandler->getAllIntegration('form', 'redirectPage'); | |
| 88 | + if (!is_wp_error($redirectPage) && !empty($redirectPage) && count($redirectPage) > 0) { | |
| 89 | + $url = json_decode($redirectPage[0]->integration_details)->url; | |
| 90 | + if (!empty($url)) { | |
| 91 | + $url = self::replaceFieldWithValue($url, $fieldValue); | |
| 117 | 92 | } |
| 93 | + $returnableData = empty($url) ? '' : esc_url_raw($url); | |
| 118 | 94 | } |
| 119 | 95 | break; |
| 120 | 96 | case 'webHooks': |
| 121 | - // Default redirect/webhook remain workflow-driven for now (revisited in the Redirect/Integration phases). | |
| 97 | + $webHooks = $integrationHandler->getAllIntegration('form', 'webHooks'); | |
| 98 | + if (!is_wp_error($webHooks) && !empty($webHooks) && 1 === count($webHooks)) { | |
| 99 | + $returnableData = ["{\"id\":{$webHooks[0]->id}}"]; | |
| 100 | + } | |
| 122 | 101 | break; |
| 123 | 102 | default: |
| 124 | 103 | break; |
| 125 | 104 | } |
| @@ -126,195 +105,27 @@ | ||
| 126 | 105 | |
| 127 | 106 | return [ |
| 128 | 107 | 'msg_id' => $messageId, |
| 129 | 108 | 'confirmation' => $returnableData, |
| 130 | - 'afterSubmit' => $afterSubmit, | |
| 131 | - 'msg_duration' => $msgDuration, | |
| 132 | 109 | ]; |
| 133 | 110 | } |
| 134 | 111 | |
| 135 | - private static function getDefaultSubmitExcludedActionIds($formId, $workFlowRun = null) | |
| 112 | + public static function calculte($firstOperand, $secondOperand, $operator) | |
| 136 | 113 | { |
| 137 | - $actionIds = [ | |
| 138 | - 'successMsg' => [], | |
| 139 | - 'redirectPage' => [], | |
| 140 | - 'mailNotify' => [], | |
| 141 | - 'integrations' => [], | |
| 142 | - ]; | |
| 143 | - $filteredActionIds = apply_filters( | |
| 144 | - 'bitform_default_submit_confirmation_excluded_action_ids', | |
| 145 | - $actionIds, | |
| 146 | - $formId, | |
| 147 | - $workFlowRun | |
| 148 | - ); | |
| 149 | - | |
| 150 | - return is_array($filteredActionIds) ? $filteredActionIds : $actionIds; | |
| 151 | - } | |
| 152 | - | |
| 153 | - public static function getDefaultMailNotifications($formId, $workFlowRun = null) | |
| 154 | - { | |
| 155 | - $mailData = []; | |
| 156 | - $emailTemplateHandler = new EmailTemplateHandler($formId); | |
| 157 | - $templates = $emailTemplateHandler->getAllTemplate(); | |
| 158 | - if (empty($templates) || is_wp_error($templates)) { | |
| 159 | - return $mailData; | |
| 114 | + switch ($operator) { | |
| 115 | + case '+': | |
| 116 | + return $firstOperand + $secondOperand; | |
| 117 | + case '-': | |
| 118 | + return $firstOperand - $secondOperand; | |
| 119 | + case '*': | |
| 120 | + return $firstOperand * $secondOperand; | |
| 121 | + case '/': | |
| 122 | + return $firstOperand / $secondOperand; | |
| 123 | + case '^': | |
| 124 | + return $firstOperand ** $secondOperand; | |
| 160 | 125 | } |
| 161 | - $excludedActionIds = self::getDefaultSubmitExcludedActionIds($formId, $workFlowRun); | |
| 162 | - $arrayFields = ['to', 'cc', 'bcc', 'replyto', 'attachment', 'mediaAttachment', 'pdfIds']; | |
| 163 | - foreach ($templates as $template) { | |
| 164 | - $status = isset($template->status) ? (int) $template->status : 1; | |
| 165 | - if ( | |
| 166 | - 1 !== $status | |
| 167 | - || isset($excludedActionIds['mailNotify'][(string) $template->id]) | |
| 168 | - ) { | |
| 169 | - continue; | |
| 170 | - } | |
| 171 | - $config = json_decode($template->config); | |
| 172 | - $details = new \stdClass(); | |
| 173 | - $details->id = wp_json_encode(['id' => (string) $template->id]); | |
| 174 | - foreach (['to', 'from', 'from_name', 'cc', 'bcc', 'replyto', 'attachment', 'mediaAttachment', 'pdfId', 'pdfIds'] as $key) { | |
| 175 | - $details->$key = isset($config->$key) ? $config->$key : (in_array($key, $arrayFields, true) ? [] : ''); | |
| 176 | - } | |
| 177 | - $mailData[] = $details; | |
| 178 | - } | |
| 179 | - return $mailData; | |
| 180 | 126 | } |
| 181 | 127 | |
| 182 | - public static function getDefaultIntegrations($formId, $workFlowRun = null) | |
| 183 | - { | |
| 184 | - $integrationIds = []; | |
| 185 | - $integrationHandler = new IntegrationHandler($formId); | |
| 186 | - $allIntegrations = $integrationHandler->getAllIntegration('form', null, 1); | |
| 187 | - if (empty($allIntegrations) || is_wp_error($allIntegrations)) { | |
| 188 | - return $integrationIds; | |
| 189 | - } | |
| 190 | - $excludedActionIds = self::getDefaultSubmitExcludedActionIds($formId, $workFlowRun); | |
| 191 | - foreach ($allIntegrations as $integration) { | |
| 192 | - if ( | |
| 193 | - 'redirectPage' === $integration->integration_type | |
| 194 | - || isset($excludedActionIds['integrations'][(string) $integration->id]) | |
| 195 | - ) { | |
| 196 | - continue; | |
| 197 | - } | |
| 198 | - // triggerData['integrations'] is a list of GROUPS; each group is an array of JSON id strings | |
| 199 | - // (Integrations::executeIntegrations requires is_array() with string members). Wrap each id. | |
| 200 | - $integrationIds[] = [wp_json_encode(['id' => (string) $integration->id])]; | |
| 201 | - } | |
| 202 | - return $integrationIds; | |
| 203 | - } | |
| 204 | - | |
| 205 | - /** | |
| 206 | - * Free implementation of the default-submit exclusion filter: any message / redirect / email / | |
| 207 | - * integration referenced by a classic/basic onsubmit workflow success action is workflow-gated, | |
| 208 | - * so it must NOT be default-executed (Pro adds the advanced-CL ids separately). Registered in Hooks. | |
| 209 | - */ | |
| 210 | - public static function workflowReferencedActionIds($actionIds, $formId, $workFlowRun = null) | |
| 211 | - { | |
| 212 | - static $cache = []; | |
| 213 | - | |
| 214 | - $actionIds = is_array($actionIds) ? $actionIds : []; | |
| 215 | - foreach (['successMsg', 'redirectPage', 'mailNotify', 'integrations'] as $bucket) { | |
| 216 | - if (empty($actionIds[$bucket]) || !is_array($actionIds[$bucket])) { | |
| 217 | - $actionIds[$bucket] = []; | |
| 218 | - } | |
| 219 | - } | |
| 220 | - | |
| 221 | - $cacheKey = (string) $formId . ':' . (string) $workFlowRun; | |
| 222 | - if (!isset($cache[$cacheKey])) { | |
| 223 | - $workFlow = new WorkFlow($formId); | |
| 224 | - $rows = $workFlow->getWorkFlow(['create_edit', $workFlowRun ?? 'create'], ['onsubmit'], null, 'workflow_order'); | |
| 225 | - $cache[$cacheKey] = self::collectReferencedActionIds(is_wp_error($rows) ? [] : $rows); | |
| 226 | - } | |
| 227 | - | |
| 228 | - foreach ($cache[$cacheKey] as $bucket => $ids) { | |
| 229 | - $actionIds[$bucket] = $actionIds[$bucket] + $ids; | |
| 230 | - } | |
| 231 | - return $actionIds; | |
| 232 | - } | |
| 233 | - | |
| 234 | - /** | |
| 235 | - * Extract the message / redirect / email / integration ids referenced by workflow-row success | |
| 236 | - * actions, grouped into the four exclusion buckets. Shared by the runtime default-submit filter | |
| 237 | - * and the one-time orphan-deactivation migration (SubmitActionFallback). | |
| 238 | - * | |
| 239 | - * @param array $rows workflow rows each having a ->workflow_condition JSON string | |
| 240 | - * | |
| 241 | - * @return array{successMsg:array,redirectPage:array,mailNotify:array,integrations:array} | |
| 242 | - */ | |
| 243 | - public static function collectReferencedActionIds($rows) | |
| 244 | - { | |
| 245 | - $referenced = ['successMsg' => [], 'redirectPage' => [], 'mailNotify' => [], 'integrations' => []]; | |
| 246 | - if (empty($rows) || !is_array($rows)) { | |
| 247 | - return $referenced; | |
| 248 | - } | |
| 249 | - foreach ($rows as $row) { | |
| 250 | - $conditions = json_decode($row->workflow_condition ?? ''); | |
| 251 | - if (empty($conditions) || !is_array($conditions)) { | |
| 252 | - continue; | |
| 253 | - } | |
| 254 | - foreach ($conditions as $condition) { | |
| 255 | - if (empty($condition->actions->success)) { | |
| 256 | - continue; | |
| 257 | - } | |
| 258 | - foreach ($condition->actions->success as $success) { | |
| 259 | - if (empty($success->type) || empty($success->details->id)) { | |
| 260 | - continue; | |
| 261 | - } | |
| 262 | - $bucket = self::actionExclusionBucket($success->type); | |
| 263 | - if (null === $bucket) { | |
| 264 | - continue; | |
| 265 | - } | |
| 266 | - foreach (self::extractActionIds($success->details->id) as $id) { | |
| 267 | - $referenced[$bucket][$id] = true; | |
| 268 | - } | |
| 269 | - } | |
| 270 | - } | |
| 271 | - } | |
| 272 | - return $referenced; | |
| 273 | - } | |
| 274 | - | |
| 275 | - private static function actionExclusionBucket($type) | |
| 276 | - { | |
| 277 | - switch ($type) { | |
| 278 | - case 'successMsg': | |
| 279 | - return 'successMsg'; | |
| 280 | - case 'redirectPage': | |
| 281 | - return 'redirectPage'; | |
| 282 | - case 'mailNotify': | |
| 283 | - return 'mailNotify'; | |
| 284 | - case 'integ': | |
| 285 | - case 'webHooks': | |
| 286 | - return 'integrations'; | |
| 287 | - default: | |
| 288 | - return null; | |
| 289 | - } | |
| 290 | - } | |
| 291 | - | |
| 292 | - private static function extractActionIds($detailId) | |
| 293 | - { | |
| 294 | - $ids = []; | |
| 295 | - $items = is_array($detailId) ? $detailId : [$detailId]; | |
| 296 | - foreach ($items as $item) { | |
| 297 | - if (!is_string($item)) { | |
| 298 | - continue; | |
| 299 | - } | |
| 300 | - $decoded = json_decode($item); | |
| 301 | - if (isset($decoded->id)) { | |
| 302 | - $ids[] = (string) $decoded->id; | |
| 303 | - } | |
| 304 | - } | |
| 305 | - return $ids; | |
| 306 | - } | |
| 307 | - | |
| 308 | - /** | |
| 309 | - * @deprecated misspelled duplicate of calculate(); kept because it is public API. Same | |
| 310 | - * divide-by-zero guard so an external caller cannot fatal either. | |
| 311 | - */ | |
| 312 | - public static function calculte($firstOperand, $secondOperand, $operator) | |
| 313 | - { | |
| 314 | - return self::calculate($firstOperand, $secondOperand, $operator); | |
| 315 | - } | |
| 316 | - | |
| 317 | 128 | public static function filterMailContentType() |
| 318 | 129 | { |
| 319 | 130 | return 'text/html'; |
| 320 | 131 | } |
| @@ -321,26 +132,11 @@ | ||
| 321 | 132 | |
| 322 | 133 | public static function evalMathExpression($stringWithFieldValue) |
| 323 | 134 | { |
| 324 | 135 | $mathExpr = $stringWithFieldValue; |
| 325 | - if (empty($mathExpr) || !\is_scalar($mathExpr)) { | |
| 136 | + if (empty($mathExpr)) { | |
| 326 | 137 | return $stringWithFieldValue; |
| 327 | 138 | } |
| 328 | - $mathExpr = (string) $mathExpr; | |
| 329 | - | |
| 330 | - // The operand/operator checks below only look at \w+ runs and operator runs, so any other | |
| 331 | - // character was invisible to them. A quoted date ('2020-10-10') therefore passed as a | |
| 332 | - // subtraction chain and its quotes later surfaced as a bogus operator token. Require the whole | |
| 333 | - // string to be made of things a formula can contain. | |
| 334 | - if (1 !== preg_match('#^[0-9.+\-*/^()\[\]{}\s]+$#', $mathExpr)) { | |
| 335 | - return $stringWithFieldValue; | |
| 336 | - } | |
| 337 | - | |
| 338 | - // A bare date is not a subtraction: 2020-10-10 must stay a date, not become 2000. | |
| 339 | - if (1 === preg_match('/^\s*\d{4}-\d{1,2}-\d{1,2}\s*$/', $mathExpr)) { | |
| 340 | - return $stringWithFieldValue; | |
| 341 | - } | |
| 342 | - | |
| 343 | 139 | preg_match_all('/[\+\-\*\/\s]+/', $mathExpr, $isMathExpr); |
| 344 | 140 | if (empty($isMathExpr[0])) { |
| 345 | 141 | return $stringWithFieldValue; |
| 346 | 142 | } |
| @@ -362,9 +158,9 @@ | ||
| 362 | 158 | $mathExpr = str_replace(' ', '', $mathExpr); |
| 363 | 159 | $mathExpr = preg_replace('/\{|\[|\(/', '(', $mathExpr); |
| 364 | 160 | $mathExpr = preg_replace('/\}|\]/', ')', $mathExpr); |
| 365 | 161 | $calculated = self::infixToPostfixEvalute($mathExpr); |
| 366 | - if (!is_null($calculated) && isset($calculated[0])) { | |
| 162 | + if (!is_null($calculated)) { | |
| 367 | 163 | return (string) $calculated[0]; |
| 368 | 164 | } |
| 369 | 165 | |
| 370 | 166 | return (string) $stringWithFieldValue; |
| @@ -388,18 +184,10 @@ | ||
| 388 | 184 | } |
| 389 | 185 | if ('(' === $token) { |
| 390 | 186 | $operatorStack[] = $token; |
| 391 | 187 | } elseif (')' === $token) { |
| 392 | - // An unbalanced ')' used to read $operatorStack[-1] and warn on every iteration; treat | |
| 393 | - // the expression as non-arithmetic instead. | |
| 394 | - if (empty($operatorStack)) { | |
| 395 | - return null; | |
| 396 | - } | |
| 397 | 188 | while ('(' !== $operatorStack[count($operatorStack) - 1]) { |
| 398 | 189 | $outputQueue[] = array_pop($operatorStack); |
| 399 | - if (empty($operatorStack)) { | |
| 400 | - return null; | |
| 401 | - } | |
| 402 | 190 | if ('(' === $operatorStack[count($operatorStack) - 1]) { |
| 403 | 191 | array_pop($operatorStack); |
| 404 | 192 | break; |
| 405 | 193 | } |
| @@ -428,22 +216,11 @@ | ||
| 428 | 216 | if (is_numeric($value)) { |
| 429 | 217 | $resultStack[] = $value; |
| 430 | 218 | continue; |
| 431 | 219 | } |
| 432 | - // A token that is neither a number nor a real operator means the input was never an | |
| 433 | - // expression — e.g. a quoted date whose quotes accumulated into a token like "'2020". | |
| 434 | - // Bail out so evalMathExpression() returns the caller's string untouched; pushing the | |
| 435 | - // failure onto the stack would end up blanking that string. | |
| 436 | - if (!\in_array($value, ['+', '-', '*', '/', '^'], true) || count($resultStack) < 2) { | |
| 437 | - return null; | |
| 438 | - } | |
| 439 | 220 | $secondOperand = array_pop($resultStack); |
| 440 | 221 | $firstOperand = array_pop($resultStack); |
| 441 | - $calculated = self::calculate($firstOperand, $secondOperand, $value); | |
| 442 | - if (\is_null($calculated)) { | |
| 443 | - return null; | |
| 444 | - } | |
| 445 | - $resultStack[] = $calculated; | |
| 222 | + $resultStack[] = self::calculate($firstOperand, $secondOperand, $value); | |
| 446 | 223 | } |
| 447 | 224 | return $resultStack; |
| 448 | 225 | } |
| 449 | 226 | |
| @@ -459,66 +236,17 @@ | ||
| 459 | 236 | |
| 460 | 237 | return isset($precedence[$operator]) ? $precedence[$operator] : 0; |
| 461 | 238 | } |
| 462 | 239 | |
| 463 | - /** | |
| 464 | - * Apply one arithmetic operator. | |
| 465 | - * | |
| 466 | - * @param mixed $firstOperand | |
| 467 | - * @param mixed $secondOperand | |
| 468 | - * @param string $operator | |
| 469 | - * | |
| 470 | - * @return float|int|null null on unknown operator, non-numeric operand, or division by zero | |
| 471 | - */ | |
| 472 | 240 | public static function calculate($firstOperand, $secondOperand, $operator) |
| 473 | 241 | { |
| 474 | - if (!is_numeric($firstOperand) || !is_numeric($secondOperand)) { | |
| 475 | - return null; | |
| 476 | - } | |
| 477 | - $firstOperand = $firstOperand + 0; | |
| 478 | - $secondOperand = $secondOperand + 0; | |
| 242 | + $calculated = [ | |
| 243 | + '+' => $firstOperand + $secondOperand, | |
| 244 | + '-' => $firstOperand - $secondOperand, | |
| 245 | + '*' => $firstOperand * $secondOperand, | |
| 246 | + '/' => $firstOperand / $secondOperand, | |
| 247 | + '^' => $firstOperand ** $secondOperand, | |
| 248 | + ]; | |
| 479 | 249 | |
| 480 | - switch ($operator) { | |
| 481 | - case '+': | |
| 482 | - return $firstOperand + $secondOperand; | |
| 483 | - case '-': | |
| 484 | - return $firstOperand - $secondOperand; | |
| 485 | - case '*': | |
| 486 | - return $firstOperand * $secondOperand; | |
| 487 | - case '/': | |
| 488 | - return 0 == $secondOperand ? null : $firstOperand / $secondOperand; | |
| 489 | - case '^': | |
| 490 | - return $firstOperand ** $secondOperand; | |
| 491 | - } | |
| 492 | - | |
| 493 | - return null; | |
| 494 | - } | |
| 495 | - | |
| 496 | - /** | |
| 497 | - * Recursively sets a nested property in a given object. | |
| 498 | - * | |
| 499 | - * This function takes an object, a string path representing nested properties | |
| 500 | - * (e.g., "fk->valid->hide"), and a value to assign. It ensures that all | |
| 501 | - * intermediate properties exist as objects before setting the final value. | |
| 502 | - * | |
| 503 | - * @param object $object The main object where properties should be set. | |
| 504 | - * @param string $path The nested property path, with keys separated by "->". | |
| 505 | - * @param mixed $value The value to assign to the final property. | |
| 506 | - * | |
| 507 | - * @return void | |
| 508 | - */ | |
| 509 | - public static function setNestedProperty(&$object, $path, $value) | |
| 510 | - { | |
| 511 | - $keys = explode('->', $path); | |
| 512 | - $key = array_shift($keys); | |
| 513 | - | |
| 514 | - if (!isset($object->$key) || !is_object($object->$key)) { | |
| 515 | - $object->$key = new \stdClass(); | |
| 516 | - } | |
| 517 | - | |
| 518 | - if (!empty($keys)) { | |
| 519 | - self::setNestedProperty($object->$key, implode('->', $keys), $value); | |
| 520 | - } else { | |
| 521 | - $object->$key = $value; | |
| 522 | - } | |
| 250 | + return isset($calculated[$operator]) ? $calculated[$operator] : ''; | |
| 523 | 251 | } |
| 524 | 252 | } |