| @@ -5,14 +5,16 @@ | ||
| 5 | 5 | use BitCode\BitForm\Core\Database\FormModel; |
| 6 | 6 | use BitCode\BitForm\Core\Form\FormManager; |
| 7 | 7 | use BitCode\BitForm\Core\Util\Render; |
| 8 | 8 | use BitCode\BitForm\Frontend\Form\FrontendFormHandler; |
| 9 | +use BitCode\BitForm\Frontend\Form\View\Conversational\ConversationalHelpers; | |
| 9 | 10 | |
| 10 | 11 | class ConversationalFormView |
| 11 | 12 | { |
| 12 | 13 | public static function preview() |
| 13 | 14 | { |
| 14 | - $requestUri = $_SERVER['REQUEST_URI']; | |
| 15 | + // Read-only: REQUEST_URI used to extract form ID from URL path for view dispatch. No state mutation. | |
| 16 | + $requestUri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : ''; | |
| 15 | 17 | $uri = explode('/', $requestUri); |
| 16 | 18 | |
| 17 | 19 | if (is_array($uri) && count($uri) > 0) { |
| 18 | 20 | $formID = $uri[count($uri) - 1]; |
| @@ -27,14 +29,16 @@ | ||
| 27 | 29 | |
| 28 | 30 | $formHTML = $formViewObject->html; |
| 29 | 31 | $font = $formViewObject->font; |
| 30 | 32 | $bfGlobals = $formViewObject->bfGlobals; |
| 33 | + $configTag = isset($formViewObject->configTag) ? $formViewObject->configTag : ''; | |
| 34 | + $formContent = isset($formViewObject->formContent) ? $formViewObject->formContent : null; | |
| 31 | 35 | |
| 32 | 36 | if (defined('BITAPPS_DEV') && BITAPPS_DEV) { |
| 33 | 37 | set_transient('bitform_form_preview', true); |
| 34 | 38 | $frontendFormHandler->generateJs($formID); |
| 35 | 39 | $title = 'BitForm Preview page'; |
| 36 | - Render::view('views/preview-page', compact('formID', 'title', 'formHTML', 'font', 'bfGlobals')); | |
| 40 | + Render::view('views/preview-page', compact('formID', 'title', 'formHTML', 'font', 'bfGlobals', 'configTag', 'formContent')); | |
| 37 | 41 | } |
| 38 | 42 | } |
| 39 | 43 | } |
| 40 | 44 | |
| @@ -39,50 +43,73 @@ | ||
| 39 | 43 | } |
| 40 | 44 | |
| 41 | 45 | private static function getCustomUrlFormId() |
| 42 | 46 | { |
| 43 | - $currentUrl = get_site_url() . $_SERVER['REQUEST_URI']; | |
| 47 | + $urlMap = get_transient('bitform_conversational_url_map'); | |
| 48 | + if (false === $urlMap) { | |
| 49 | + $urlMap = self::buildConversationalUrlMap(); | |
| 50 | + set_transient('bitform_conversational_url_map', $urlMap, DAY_IN_SECONDS); | |
| 51 | + } | |
| 52 | + | |
| 53 | + if (empty($urlMap)) { | |
| 54 | + return null; | |
| 55 | + } | |
| 56 | + | |
| 57 | + $currentUrl = get_site_url() . (isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : ''); | |
| 44 | 58 | $parsedCurrentUrl = wp_parse_url($currentUrl); |
| 59 | + | |
| 60 | + foreach ($urlMap as $formID => $customUrlSlug) { | |
| 61 | + $customUrl = get_site_url() . '/' . $customUrlSlug; | |
| 62 | + $parsedCustomUrl = wp_parse_url($customUrl); | |
| 63 | + $pathMatched = isset($parsedCustomUrl['path']) && $parsedCustomUrl['path'] === ($parsedCurrentUrl['path'] ?? ''); | |
| 64 | + if (!$pathMatched) { | |
| 65 | + continue; | |
| 66 | + } | |
| 67 | + if (!isset($parsedCustomUrl['query'])) { | |
| 68 | + return $formID; | |
| 69 | + } | |
| 70 | + parse_str($parsedCustomUrl['query'], $parsedCustomQueries); | |
| 71 | + parse_str($parsedCurrentUrl['query'] ?? '', $parsedCurrentQueries); | |
| 72 | + if (empty(array_diff_assoc($parsedCustomQueries, $parsedCurrentQueries))) { | |
| 73 | + return $formID; | |
| 74 | + } | |
| 75 | + } | |
| 76 | + | |
| 77 | + return null; | |
| 78 | + } | |
| 79 | + | |
| 80 | + private static function buildConversationalUrlMap() | |
| 81 | + { | |
| 45 | 82 | $formModel = new FormModel(); |
| 46 | - $forms = $formModel->get( | |
| 47 | - ['id', 'form_content'] | |
| 48 | - ); | |
| 49 | - | |
| 50 | - if (!is_wp_error($forms)) { | |
| 51 | - foreach ($forms as $form) { | |
| 52 | - $formID = $form->id; | |
| 53 | - $formContent = json_decode($form->form_content); | |
| 54 | - $isStandaloneActive = !empty($formContent->formInfo->standaloneSettings->active); | |
| 55 | - $isConversationalActive = !empty($formContent->formInfo->conversationalSettings->enable); | |
| 56 | - if ($isStandaloneActive && $isConversationalActive) { | |
| 57 | - $standaloneSettings = $formContent->formInfo->standaloneSettings; | |
| 58 | - $hasCustomUrl = !empty($standaloneSettings->customUrl); | |
| 59 | - if (!$hasCustomUrl) { | |
| 60 | - continue; | |
| 61 | - } | |
| 62 | - $customUrl = get_site_url() . '/' . $standaloneSettings->customUrl; | |
| 63 | - $parsedCustomUrl = wp_parse_url($customUrl); | |
| 64 | - $pathMatched = $parsedCustomUrl['path'] === $parsedCurrentUrl['path']; | |
| 65 | - if (!$pathMatched) { | |
| 66 | - continue; | |
| 67 | - } | |
| 68 | - if (!isset($parsedCustomUrl['query'])) { | |
| 69 | - return $formID; | |
| 70 | - } | |
| 71 | - parse_str($parsedCustomUrl['query'], $parsedCustomQueries); | |
| 72 | - parse_str($parsedCurrentUrl['query'], $parsedCurrentQueries); | |
| 73 | - $diff = array_diff_assoc($parsedCustomQueries, $parsedCurrentQueries); | |
| 74 | - if (empty($diff)) { | |
| 75 | - return $formID; | |
| 76 | - } | |
| 77 | - } | |
| 83 | + $forms = $formModel->get(['id', 'form_content']); | |
| 84 | + $urlMap = []; | |
| 85 | + if (is_wp_error($forms) || !is_array($forms)) { | |
| 86 | + return $urlMap; | |
| 87 | + } | |
| 88 | + foreach ($forms as $form) { | |
| 89 | + $formContent = json_decode($form->form_content); | |
| 90 | + if (empty($formContent->formInfo->standaloneSettings->active)) { | |
| 91 | + continue; | |
| 78 | 92 | } |
| 93 | + if (empty($formContent->formInfo->conversationalSettings->enable)) { | |
| 94 | + continue; | |
| 95 | + } | |
| 96 | + $standaloneSettings = $formContent->formInfo->standaloneSettings; | |
| 97 | + if (empty($standaloneSettings->customUrl)) { | |
| 98 | + continue; | |
| 99 | + } | |
| 100 | + $urlMap[$form->id] = $standaloneSettings->customUrl; | |
| 79 | 101 | } |
| 102 | + return $urlMap; | |
| 80 | 103 | } |
| 81 | 104 | |
| 82 | 105 | public static function conversationalFormView() |
| 83 | 106 | { |
| 84 | - $formID = isset($_GET['bit-conversational-form']) ? $_GET['bit-conversational-form'] : ''; | |
| 107 | + if (is_admin()) { | |
| 108 | + return; | |
| 109 | + } | |
| 110 | + // Read-only: form ID and preview flag from query string for conversational form dispatch. No state mutation. | |
| 111 | + $formID = isset($_GET['bit-conversational-form']) ? sanitize_text_field(wp_unslash($_GET['bit-conversational-form'])) : ''; | |
| 85 | 112 | $formType = 'conversational'; |
| 86 | 113 | if (empty($formID)) { |
| 87 | 114 | $formID = self::getCustomUrlFormId(); |
| 88 | 115 | } |
| @@ -91,11 +118,16 @@ | ||
| 91 | 118 | return ''; |
| 92 | 119 | } |
| 93 | 120 | |
| 94 | 121 | $formID = intval($formID); |
| 122 | + | |
| 123 | + $isPreview = isset($_GET['bf_preview']); | |
| 124 | + | |
| 125 | + ConversationalHelpers::setPreviewMode($isPreview); | |
| 126 | + | |
| 95 | 127 | $attr = ['type'=> $formType, 'form_id' => $formID, 'form_preview' => true]; |
| 96 | 128 | |
| 97 | - $FormManager = new FormManager($formID); | |
| 129 | + $FormManager = FormManager::getInstance($formID); | |
| 98 | 130 | $formContent = $FormManager->getFormContent(); |
| 99 | 131 | if (empty($formContent->formInfo->conversationalSettings->enable)) { |
| 100 | 132 | return; |
| 101 | 133 | } |
| @@ -109,13 +141,15 @@ | ||
| 109 | 141 | |
| 110 | 142 | $formHTML = $formViewObject->html; |
| 111 | 143 | $font = $formViewObject->font; |
| 112 | 144 | $bfGlobals = $formViewObject->bfGlobals; |
| 145 | + $configTag = isset($formViewObject->configTag) ? $formViewObject->configTag : ''; | |
| 146 | + $formContent = isset($formViewObject->formContent) ? $formViewObject->formContent : null; | |
| 113 | 147 | |
| 114 | 148 | set_transient('bitform_form_preview', true); |
| 115 | 149 | $frontendFormHandler->generateJs($formID, null, $formType); |
| 116 | 150 | $title = 'Bit Form'; |
| 117 | - Render::view('views/conversational-form', compact('formID', 'title', 'formHTML', 'font', 'bfGlobals')); | |
| 151 | + Render::view('views/conversational-form', compact('formID', 'title', 'formHTML', 'font', 'bfGlobals', 'configTag', 'isPreview', 'formContent')); | |
| 118 | 152 | |
| 119 | 153 | exit(200); |
| 120 | 154 | } |
| 121 | 155 | } |