| @@ -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,186 +105,11 @@ | ||
| 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) | |
| 136 | - { | |
| 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; | |
| 160 | - } | |
| 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 | - } | |
| 181 | - | |
| 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 | 112 | public static function calculte($firstOperand, $secondOperand, $operator) |
| 309 | 113 | { |
| 310 | 114 | switch ($operator) { |
| 311 | 115 | case '+': |
| @@ -443,35 +247,6 @@ | ||
| 443 | 247 | '^' => $firstOperand ** $secondOperand, |
| 444 | 248 | ]; |
| 445 | 249 | |
| 446 | 250 | return isset($calculated[$operator]) ? $calculated[$operator] : ''; |
| 447 | - } | |
| 448 | - | |
| 449 | - /** | |
| 450 | - * Recursively sets a nested property in a given object. | |
| 451 | - * | |
| 452 | - * This function takes an object, a string path representing nested properties | |
| 453 | - * (e.g., "fk->valid->hide"), and a value to assign. It ensures that all | |
| 454 | - * intermediate properties exist as objects before setting the final value. | |
| 455 | - * | |
| 456 | - * @param object $object The main object where properties should be set. | |
| 457 | - * @param string $path The nested property path, with keys separated by "->". | |
| 458 | - * @param mixed $value The value to assign to the final property. | |
| 459 | - * | |
| 460 | - * @return void | |
| 461 | - */ | |
| 462 | - public static function setNestedProperty(&$object, $path, $value) | |
| 463 | - { | |
| 464 | - $keys = explode('->', $path); | |
| 465 | - $key = array_shift($keys); | |
| 466 | - | |
| 467 | - if (!isset($object->$key) || !is_object($object->$key)) { | |
| 468 | - $object->$key = new \stdClass(); | |
| 469 | - } | |
| 470 | - | |
| 471 | - if (!empty($keys)) { | |
| 472 | - self::setNestedProperty($object->$key, implode('->', $keys), $value); | |
| 473 | - } else { | |
| 474 | - $object->$key = $value; | |
| 475 | - } | |
| 476 | 251 | } |
| 477 | 252 | } |