PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 6.2.14
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v6.2.14
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
← All changes | app/Modules/Form/Form.php +538 -227 3.6.606.2.14 View file →
@@ -3,13 +3,18 @@
3 3 namespace FluentForm\App\Modules\Form;
4 4
5 5 use FluentForm\App\Helpers\Helper;
6 6 use FluentForm\App\Modules\Acl\Acl;
7 +use FluentForm\App\Modules\Payments\PaymentHelper;
8 +use FluentForm\App\Services\FormBuilder\RatingIcon;
7 9 use FluentForm\Framework\Foundation\Application;
10 +use FluentForm\Framework\Helpers\ArrayHelper;
8 11
9 12 class Form
10 13 {
11 14 /**
15 + * Request object
16 + *
12 17 * @var \FluentForm\Framework\Request\Request $request
13 18 */
14 19 protected $request;
15 20
@@ -19,9 +24,8 @@
19 24 * @var array $defaultSettings
20 25 */
21 26 protected $defaultSettings;
22 27
23 -
24 28 /**
25 29 * Set this value when we need predefined default notifications.
26 30 *
27 31 * @var array $defaultNotifications
@@ -39,15 +43,17 @@
39 43
40 44 protected $formType = 'form';
41 45
42 46 protected $hasPayment = 0;
47 + /**
48 + * @var \FluentForm\Framework\Database\Query\Builder
49 + */
50 + protected $model = null;
43 51
44 52 /**
45 53 * Form constructor.
46 54 *
47 55 * @param \FluentForm\Framework\Foundation\Application $application
48 - *
49 - * @throws \Exception
50 56 */
51 57 public function __construct(Application $application)
52 58 {
53 59 $this->request = $application->request;
@@ -55,93 +61,31 @@
55 61 }
56 62
57 63 /**
58 64 * Get all forms from database
59 - *
60 - * @return void
61 - * @throws \Exception
62 65 */
63 66 public function index()
64 67 {
65 - $search = $this->request->get('search');
66 - $status = $this->request->get('status');
68 + $forms = fluentFormApi('forms')->forms([
69 + 'search' => $this->request->get('search'),
70 + 'status' => $this->request->get('status'),
71 + 'filter_by' => $this->request->get('filter_by', 'all'),
72 + 'date_range' => $this->request->get('date_range', []),
73 + 'sort_column' => $this->request->get('sort_column', 'id'),
74 + 'sort_by' => $this->request->get('sort_by', 'DESC'),
75 + 'per_page' => $this->request->get('per_page', 10),
76 + 'page' => $this->request->get('page', 1),
77 + ]);
67 78
68 - $shortColumn = $this->request->get('sort_column', 'id');
69 - $sortBy = $this->request->get('sort_by', 'DESC');
70 -
71 - $query = wpFluent()->table('fluentform_forms')
72 - ->orderBy($shortColumn, $sortBy);
73 -
74 - if ($status && $status != 'all') {
75 - $query->where('status', $status);
76 - }
77 -
78 - if ($search) {
79 - $query->where(function ($q) use ($search) {
80 - $q->where('id', 'LIKE', '%' . $search . '%');
81 - $q->orWhere('title', 'LIKE', '%' . $search . '%');
82 - });
83 - }
84 -
85 - $forms = $query->paginate();
86 -
87 - foreach ($forms['data'] as $form) {
88 - $form->preview_url = site_url('?fluentform_pages=1&preview_id=' . $form->id) . '#ff_preview';;
89 - $form->edit_url = $this->getAdminPermalink('editor', $form);
90 - $form->settings_url = $this->getSettingsUrl($form);
91 - $form->entries_url = $this->getAdminPermalink('entries', $form);
92 - $form->analytics_url = $this->getAdminPermalink('analytics', $form);
93 - $form->total_views = $this->getFormViewCount($form->id);
94 - $form->total_views = $this->getFormViewCount($form->id);
95 - $form->total_Submissions = $this->getSubmissionCount($form->id);
96 - $form->unread_count = $this->getUnreadCount($form->id);
97 - $form->conversion = $this->getConversionRate($form);
98 - unset($form->form_fields);
99 - }
100 -
101 79 wp_send_json($forms, 200);
102 80 }
103 81
104 - private function getFormViewCount($formId)
105 - {
106 - $hasCount = wpFluent()
107 - ->table('fluentform_form_meta')
108 - ->where('meta_key', '_total_views')
109 - ->where('form_id', $formId)
110 - ->first();
111 -
112 - if ($hasCount) {
113 - return intval($hasCount->value);
114 - }
115 -
116 - return 0;
117 - }
118 -
119 - private function getSubmissionCount($formID)
120 - {
121 - return wpFluent()
122 - ->table('fluentform_submissions')
123 - ->where('form_id', $formID)
124 - ->where('status', '!=', 'trashed')
125 - ->count();
126 - }
127 -
128 - private function getConversionRate($form)
129 - {
130 - if (!$form->total_Submissions)
131 - return 0;
132 -
133 - if (!$form->total_views)
134 - return 0;
135 -
136 - return ceil(($form->total_Submissions / $form->total_views) * 100);
137 - }
138 -
139 82 /**
140 83 * Create a form from backend/editor
141 - * @return void
84 + *
85 + * @return void|array
142 86 */
143 - public function store()
87 + public function store($returnJSON = true)
144 88 {
145 89 $type = $this->request->get('type', $this->formType);
146 90 $title = $this->request->get('title', 'My New Form');
147 91 $status = $this->request->get('status', 'published');
@@ -149,14 +93,14 @@
149 93
150 94 $now = current_time('mysql');
151 95
152 96 $insertData = [
153 - 'title' => $title,
154 - 'type' => $type,
155 - 'status' => $status,
97 + 'title' => $title,
98 + 'type' => $type,
99 + 'status' => $status,
156 100 'created_by' => $createdBy,
157 101 'created_at' => $now,
158 - 'updated_at' => $now
102 + 'updated_at' => $now,
159 103 ];
160 104
161 105 if ($this->formFields) {
162 106 $insertData['form_fields'] = $this->formFields;
@@ -161,104 +105,132 @@
161 105 if ($this->formFields) {
162 106 $insertData['form_fields'] = $this->formFields;
163 107 }
164 108
165 - if($this->hasPayment) {
109 + if ($this->hasPayment) {
166 110 $insertData['has_payment'] = $this->hasPayment;
167 111 }
168 112
169 - $formId = $this->model->insert($insertData);
113 + $formId = $this->model->insertGetId($insertData);
170 114
171 115 // Rename the form name here
172 - wpFluent()->table('fluentform_forms')->where('id', $formId)->update(array(
173 - 'title' => $title . ' (#' . $formId . ')'
174 - ));
116 + wpFluent()->table('fluentform_forms')->where('id', $formId)->update([
117 + 'title' => $title . ' (#' . $formId . ')',
118 + ]);
175 119
176 - if($this->metas && is_array($this->metas)) {
120 + if ($this->metas && is_array($this->metas)) {
177 121 foreach ($this->metas as $meta) {
178 122 $meta['value'] = trim(preg_replace('/\s+/', ' ', $meta['value']));
179 123
180 124 wpFluent()->table('fluentform_form_meta')
181 - ->insert(array(
182 - 'form_id' => $formId,
125 + ->insert([
126 + 'form_id' => $formId,
183 127 'meta_key' => $meta['meta_key'],
184 - 'value' => $meta['value']
185 - ));
128 + 'value' => $meta['value'],
129 + ]);
186 130 }
187 131 } else {
188 132 // add default form settings now
189 133 $defaultSettings = $this->defaultSettings ?: $this->getFormsDefaultSettings($formId);
134 +
135 + $defaultSettings = apply_filters_deprecated(
136 + 'fluentform_create_default_settings',
137 + [
138 + $defaultSettings
139 + ],
140 + FLUENTFORM_FRAMEWORK_UPGRADE,
141 + 'fluentform/create_default_settings',
142 + 'Use fluentform/create_default_settings instead of fluentform_create_default_settings.'
143 + );
190 144
191 - $defaultSettings = apply_filters('fluentform_create_default_settings', $defaultSettings);
145 + $defaultSettings = apply_filters('fluentform/create_default_settings', $defaultSettings);
192 146
193 147 wpFluent()->table('fluentform_form_meta')
194 - ->insert(array(
195 - 'form_id' => $formId,
148 + ->insert([
149 + 'form_id' => $formId,
196 150 'meta_key' => 'formSettings',
197 - 'value' => json_encode($defaultSettings)
198 - ));
151 + 'value' => json_encode($defaultSettings),
152 + ]);
199 153
200 154 if ($this->defaultNotifications) {
201 155 wpFluent()->table('fluentform_form_meta')
202 - ->insert(array(
203 - 'form_id' => $formId,
156 + ->insert([
157 + 'form_id' => $formId,
204 158 'meta_key' => 'notifications',
205 - 'value' => json_encode($this->defaultNotifications)
206 - ));
159 + 'value' => json_encode($this->defaultNotifications),
160 + ]);
207 161 }
208 162 }
209 163
210 - do_action('fluentform_inserted_new_form', $formId, $insertData);
164 + do_action_deprecated(
165 + 'fluentform_inserted_new_form',
166 + [
167 + $formId,
168 + $insertData
169 + ],
170 + FLUENTFORM_FRAMEWORK_UPGRADE,
171 + 'fluentform/inserted_new_form',
172 + 'Use fluentform/inserted_new_form instead of fluentform_inserted_new_form.'
173 + );
211 174
212 - wp_send_json_success(array(
213 - 'formId' => $formId,
175 + do_action('fluentform/inserted_new_form', $formId, $insertData);
176 +
177 + $data = [
178 + 'formId' => $formId,
214 179 'redirect_url' => admin_url('admin.php?page=fluent_forms&form_id=' . $formId . '&route=editor'),
215 - 'message' => __('Successfully created a form.', 'fluentform')
216 - ), 200);
180 + 'message' => __('Successfully created a form.', 'fluentform'),
181 + ];
182 +
183 + if ($returnJSON) {
184 + wp_send_json_success($data, 200);
185 + }
186 +
187 + return $data;
217 188 }
218 189
219 190 public function getFormsDefaultSettings($formId = false)
220 191 {
221 - $defaultSettings = array(
222 - 'confirmation' => array(
223 - 'redirectTo' => 'samePage',
224 - 'messageToShow' => __('Thank you for your message. We will get in touch with you shortly', 'fluentform'),
225 - 'customPage' => null,
192 + $defaultSettings = [
193 + 'confirmation' => [
194 + 'redirectTo' => 'samePage',
195 + 'messageToShow' => __('Thank you for your message. We will get in touch with you shortly.', 'fluentform'),
196 + 'customPage' => null,
226 197 'samePageFormBehavior' => 'hide_form',
227 - 'customUrl' => null
228 - ),
229 - 'restrictions' => array(
230 - 'limitNumberOfEntries' => array(
231 - 'enabled' => false,
198 + 'customUrl' => null,
199 + ],
200 + 'restrictions' => [
201 + 'limitNumberOfEntries' => [
202 + 'enabled' => false,
232 203 'numberOfEntries' => null,
233 - 'period' => 'total',
234 - 'limitReachedMsg' => 'Maximum number of entries exceeded.'
235 - ),
236 - 'scheduleForm' => array(
237 - 'enabled' => false,
238 - 'start' => null,
239 - 'end' => null,
240 - 'pendingMsg' => __("Form submission is not started yet.", 'fluentform'),
241 - 'expiredMsg' => __("Form submission is now closed.", 'fluentform')
242 - ),
243 - 'requireLogin' => array(
244 - 'enabled' => false,
204 + 'period' => 'total',
205 + 'limitReachedMsg' => 'Maximum number of entries exceeded.',
206 + ],
207 + 'scheduleForm' => [
208 + 'enabled' => false,
209 + 'start' => null,
210 + 'end' => null,
211 + 'selectedDays' => null,
212 + 'pendingMsg' => __('Form submission is not started yet.', 'fluentform'),
213 + 'expiredMsg' => __('Form submission is now closed.', 'fluentform'),
214 + ],
215 + 'requireLogin' => [
216 + 'enabled' => false,
245 217 'requireLoginMsg' => 'You must be logged in to submit the form.',
246 - ),
218 + ],
247 219 'denyEmptySubmission' => [
248 220 'enabled' => false,
249 221 'message' => __('Sorry, you cannot submit an empty form. Let\'s hear what you wanna say.', 'fluentform'),
250 - ]
251 - ),
252 - 'layout' => array(
253 - 'labelPlacement' => 'top',
254 - 'helpMessagePlacement' => 'with_label',
222 + ],
223 + ],
224 + 'layout' => [
225 + 'labelPlacement' => 'top',
226 + 'helpMessagePlacement' => 'with_label',
255 227 'errorMessagePlacement' => 'inline',
256 - 'cssClassName' => '',
257 - 'asteriskPlacement' => 'asterisk-right'
258 - ),
259 - 'delete_entry_on_submission' => 'no'
260 - );
228 + 'cssClassName' => '',
229 + 'asteriskPlacement' => 'asterisk-right'
230 + ],
231 + 'delete_entry_on_submission' => 'no',
232 + ];
261 233
262 234 if ($formId) {
263 235 $value = $this->getMeta($formId, 'formSettings', true);
264 236 if ($value) {
@@ -276,24 +248,24 @@
276 248
277 249 public function getAdvancedValidationSettings($formId)
278 250 {
279 251 $settings = [
280 - 'status' => false,
281 - 'type' => 'all',
252 + 'status' => false,
253 + 'type' => 'all',
282 254 'conditions' => [
283 255 [
284 - 'field' => '',
256 + 'field' => '',
285 257 'operator' => '=',
286 - 'value' => ''
287 - ]
258 + 'value' => '',
259 + ],
288 260 ],
289 - 'error_message' => '',
290 - 'validation_type' => 'fail_on_condition_met'
261 + 'error_message' => '',
262 + 'validation_type' => 'fail_on_condition_met',
291 263 ];
292 264
293 265 $metaSettings = $this->getMeta($formId, 'advancedValidationSettings', true);
294 266
295 - if($metaSettings && is_array($metaSettings)) {
267 + if ($metaSettings && is_array($metaSettings)) {
296 268 $settings = wp_parse_args($metaSettings, $settings);
297 269 }
298 270
299 271 return $settings;
@@ -305,9 +277,9 @@
305 277 ->where('form_id', $formId)
306 278 ->where('meta_key', $metaKey)
307 279 ->first();
308 280 if ($settingsMeta) {
309 - if($isJson) {
281 + if ($isJson) {
310 282 return \json_decode($settingsMeta->value, true);
311 283 } else {
312 284 return $settingsMeta->value;
313 285 }
@@ -321,30 +293,37 @@
321 293 ->where('form_id', $formId)
322 294 ->where('meta_key', $metaKey)
323 295 ->first();
324 296
325 - if(is_array($metaValue) || is_object($metaValue)) {
297 + if (is_array($metaValue) || is_object($metaValue)) {
326 298 $metaValue = \json_encode($metaValue);
327 299 }
328 300
329 - if($exist) {
301 + if ($exist) {
330 302 return wpFluent()->table('fluentform_form_meta')
331 303 ->where('id', $exist->id)
332 304 ->update([
333 - 'value' => $metaValue
305 + 'value' => $metaValue,
334 306 ]);
335 307 }
336 308
337 - return wpFluent()->table('fluentform_form_meta')->insert([
338 - 'form_id' => $formId,
309 + return wpFluent()->table('fluentform_form_meta')->insertGetId([
310 + 'form_id' => $formId,
339 311 'meta_key' => $metaKey,
340 - 'value' => $metaValue
312 + 'value' => $metaValue,
341 313 ]);
342 314 }
343 315
316 + public function deleteMeta($formId, $metaKey)
317 + {
318 + return wpFluent()->table('fluentform_form_meta')
319 + ->where('form_id', $formId)
320 + ->where('meta_key', $metaKey)
321 + ->delete();
322 + }
323 +
344 324 /**
345 325 * Find/Read a from from the database
346 - * @return void
347 326 */
348 327 public function find()
349 328 {
350 329 $form = $this->fetchForm($this->request->get('formId'));
@@ -353,8 +332,9 @@
353 332
354 333 /**
355 334 * Fetch a from from the database
356 335 * Note: required for ninja-tables
336 + *
357 337 * @return mixed
358 338 */
359 339 public function fetchForm($formId)
360 340 {
@@ -362,28 +342,36 @@
362 342 }
363 343
364 344 /**
365 345 * Save/update a form from backend/editor
366 - * @return void
367 - * @throws \WpFluent\Exception
368 346 */
369 347 public function update()
370 348 {
371 349 $formId = $this->request->get('formId');
372 - $title = $this->request->get('title');
350 + $title = sanitize_text_field($this->request->get('title'));
373 351 $status = $this->request->get('status', 'published');
374 352
375 353 $this->validate();
376 354
377 355 $data = [
378 - 'title' => $title,
379 - 'status' => $status,
380 - 'updated_at' => current_time('mysql')
356 + 'title' => $title,
357 + 'status' => $status,
358 + 'updated_at' => current_time('mysql'),
381 359 ];
382 360
383 -
384 361 if ($formFields = $this->request->get('formFields')) {
385 - $formFields = apply_filters('fluentform_form_fields_update', $formFields, $formId);
362 + $formFields = apply_filters_deprecated(
363 + 'fluentform_form_fields_update',
364 + [
365 + $formFields,
366 + $formId
367 + ],
368 + FLUENTFORM_FRAMEWORK_UPGRADE,
369 + 'fluentform/form_fields_update',
370 + 'Use fluentform/form_fields_update instead of fluentform_form_fields_update.'
371 + );
372 + $formFields = apply_filters('fluentform/form_fields_update', $formFields, $formId);
373 + $formFields = $this->sanitizeFields($formFields);
386 374 $data['form_fields'] = $formFields;
387 375 }
388 376
389 377 $this->model->where('id', $formId)->update($data);
@@ -391,25 +379,141 @@
391 379 $form = $this->fetchForm($formId);
392 380
393 381 if (FormFieldsParser::hasPaymentFields($form)) {
394 382 $this->model->where('id', $formId)->update([
395 - 'has_payment' => 1
383 + 'has_payment' => 1,
396 384 ]);
397 - } else if ($form->has_payment) {
385 + } elseif ($form->has_payment) {
398 386 $this->model->where('id', $formId)->update([
399 - 'has_payment' => 0
387 + 'has_payment' => 0,
400 388 ]);
401 389 }
402 390
391 + $emailInputs = FormFieldsParser::getElement($form, ['input_email'], ['element', 'attributes']);
392 + if ($emailInputs) {
393 + $emailInput = array_shift($emailInputs);
394 + $emailInputName = ArrayHelper::get($emailInput, 'attributes.name');
395 + $this->updateMeta($formId, '_primary_email_field', $emailInputName);
396 + } else {
397 + $this->updateMeta($formId, '_primary_email_field', '');
398 + }
399 +
403 400 wp_send_json([
404 - 'message' => __('The form is successfully updated.', 'fluentform')
401 + 'message' => __('The form is successfully updated.', 'fluentform'),
405 402 ], 200);
406 403 }
407 404
405 + private function sanitizeFields($formFields)
406 + {
407 + if (fluentformCanUnfilteredHTML()) {
408 + return $formFields;
409 + }
410 +
411 + $fieldsArray = json_decode($formFields, true);
412 +
413 + if (isset($fieldsArray['submitButton'])) {
414 + $fieldsArray['submitButton']['settings']['button_ui']['text'] = fluentform_sanitize_html($fieldsArray['submitButton']['settings']['button_ui']['text']);
415 + if (!empty($fieldsArray['submitButton']['settings']['button_ui']['img_url'])) {
416 + $fieldsArray['submitButton']['settings']['button_ui']['img_url'] = sanitize_url($fieldsArray['submitButton']['settings']['button_ui']['img_url']);
417 + }
418 + }
419 +
420 + $fieldsArray['fields'] = $this->sanitizeFieldMaps($fieldsArray['fields']);
421 +
422 + return json_encode($fieldsArray);
423 + }
424 +
425 + private function sanitizeFieldMaps($fields)
426 + {
427 + if (!is_array($fields)) {
428 + return $fields;
429 + }
430 +
431 + $attributesMap = [
432 + 'name' => 'sanitize_key',
433 + 'value' => 'sanitize_textarea_field',
434 + 'id' => 'sanitize_key',
435 + 'class' => 'sanitize_text_field',
436 + 'placeholder' => 'sanitize_text_field',
437 + ];
438 + $attributesKeys = array_keys($attributesMap);
439 + $settingsMap = [
440 + 'container_class' => 'sanitize_text_field',
441 + 'label' => 'wp_kses_post',
442 + 'label_placement' => 'sanitize_text_field',
443 + 'help_message' => 'wp_kses_post',
444 + 'admin_field_label' => 'sanitize_text_field',
445 + 'prefix_label' => 'sanitize_text_field',
446 + 'suffix_label' => 'sanitize_text_field',
447 + 'icon_source' => 'sanitize_key',
448 + 'icon_type' => 'sanitize_key',
449 + 'custom_icon_svg' => [RatingIcon::class, 'sanitizeCustomSvg'],
450 + 'inactive_color' => [RatingIcon::class, 'sanitizeColor'],
451 + 'active_color' => [RatingIcon::class, 'sanitizeColor'],
452 + 'unique_validation_message' => 'sanitize_text_field',
453 + 'advanced_options' => 'fluentform_options_sanitize',
454 + 'html_codes' => 'fluentform_sanitize_html',
455 + 'enable_crop' => 'sanitize_text_field',
456 + 'crop_mode' => 'sanitize_text_field',
457 + 'crop_ratio' => 'sanitize_text_field',
458 + 'crop_width' => 'absint',
459 + 'crop_height' => 'absint',
460 + 'enforce_image_dimensions' => 'sanitize_text_field',
461 + ];
462 + $settingsKeys = array_keys($settingsMap);
463 + $stylePrefMap = [
464 + 'layout' => 'sanitize_key',
465 + 'media' => 'sanitize_url',
466 + 'alt_text' => 'sanitize_text_field',
467 + ];
468 + $stylePrefKeys = array_keys($stylePrefMap);
469 +
470 + foreach ($fields as $fieldIndex => $field) {
471 + $element = ArrayHelper::get($field, 'element');
472 +
473 + if ('container' == $element) {
474 + $columns = $field['columns'];
475 + foreach ($columns as $columnIndex => $column) {
476 + $fields[$fieldIndex]['columns'][$columnIndex]['fields'] = $this->sanitizeFieldMaps($column['fields']);
477 + }
478 + return $fields;
479 + }
480 +
481 + /*
482 + * Handle Name or address fields
483 + */
484 + if (!empty($field['fields'])) {
485 + $fields[$fieldIndex]['fields'] = $this->sanitizeFieldMaps($field['fields']);
486 + return $fields;
487 + }
488 +
489 + if (!empty($field['attributes'])) {
490 + $attributes = array_filter(ArrayHelper::only($field['attributes'], $attributesKeys));
491 + foreach ($attributes as $key => $value) {
492 + $fields[$fieldIndex]['attributes'][$key] = call_user_func($attributesMap[$key], $value);
493 + }
494 + }
495 +
496 + if (!empty($field['settings'])) {
497 + $settings = array_filter(ArrayHelper::only($field['settings'], $settingsKeys));
498 + foreach ($settings as $key => $value) {
499 + $fields[$fieldIndex]['settings'][$key] = call_user_func($settingsMap[$key], $value);
500 + }
501 + }
502 +
503 + if (!empty($field['style_pref'])) {
504 + $settings = array_filter(ArrayHelper::only($field['style_pref'], $stylePrefKeys));
505 + foreach ($settings as $key => $value) {
506 + $fields[$fieldIndex]['style_pref'][$key] = call_user_func($stylePrefMap[$key], $value);
507 + }
508 + }
509 + }
510 +
511 + return $fields;
512 + }
513 +
408 514 /**
409 515 * Delete a from from database
410 - * @return void
411 - * @throws \WpFluent\Exception
412 516 */
413 517 public function delete()
414 518 {
415 519 $formId = $this->request->get('formId');
@@ -417,16 +521,14 @@
417 521 $this->model->where('id', $formId)->delete();
418 522
419 523 $maybeErrors = $this->deleteFormAssests($formId);
420 524
421 -
422 525 wp_send_json([
423 526 'message' => __('Successfully deleted the form.', 'fluentform'),
424 - 'errors' => $maybeErrors
527 + 'errors' => $maybeErrors,
425 528 ], 200);
426 529 }
427 530
428 -
429 531 protected function deleteFormAssests($formId)
430 532 {
431 533 // Now Let's delete associate items
432 534 wpFluent()->table('fluentform_submissions')
@@ -440,8 +542,12 @@
440 542 wpFluent()->table('fluentform_entry_details')
441 543 ->where('form_id', $formId)
442 544 ->delete();
443 545
546 + wpFluent()->table('fluentform_form_meta')
547 + ->where('form_id', $formId)
548 + ->delete();
549 +
444 550 wpFluent()->table('fluentform_form_analytics')
445 551 ->where('form_id', $formId)
446 552 ->delete();
447 553
@@ -446,27 +552,20 @@
446 552 ->delete();
447 553
448 554 wpFluent()->table('fluentform_logs')
449 555 ->where('parent_source_id', $formId)
450 - ->whereIn('source_type', ['submission_item', 'form_item'])
556 + ->whereIn('source_type', ['submission_item', 'form_item', 'draft_submission_meta'])
451 557 ->delete();
452 558
453 559 ob_start();
454 - if (defined('FLUENTFORMPRO')) {
560 + if (PaymentHelper::hasPaymentSettings()) {
455 561 try {
456 - wpFluent()->table('fluentform_order_items')
457 - ->where('form_id', $formId)
458 - ->delete();
459 - wpFluent()->table('fluentform_subscriptions')
460 - ->where('form_id', $formId)
461 - ->delete();
462 - wpFluent()->table('fluentform_transactions')
463 - ->where('form_id', $formId)
464 - ->delete();
562 + \FluentForm\App\Models\OrderItem::where('form_id', $formId)->delete();
563 + \FluentForm\App\Models\Transaction::where('form_id', $formId)->delete();
465 564 } catch (\Exception $exception) {
466 -
467 565 }
468 566 }
567 +
469 568 $errors = ob_get_clean();
470 569 return $errors;
471 570 }
472 571
@@ -471,10 +570,8 @@
471 570 }
472 571
473 572 /**
474 573 * Duplicate a from
475 - * @return void
476 - * @throws \WpFluent\Exception
477 574 */
478 575 public function duplicate()
479 576 {
480 577 $formId = absint($this->request->get('formId'));
@@ -479,29 +576,29 @@
479 576 {
480 577 $formId = absint($this->request->get('formId'));
481 578 $form = $this->model->where('id', $formId)->first();
482 579
483 - $data = array(
484 - 'title' => $form->title,
485 - 'status' => $form->status,
580 + $data = [
581 + 'title' => $form->title,
582 + 'status' => $form->status,
486 583 'appearance_settings' => $form->appearance_settings,
487 - 'form_fields' => $form->form_fields,
488 - 'type' => $form->type,
489 - 'has_payment' => $form->has_payment,
490 - 'conditions' => $form->conditions,
491 - 'created_by' => get_current_user_id(),
492 - 'created_at' => current_time('mysql'),
493 - 'updated_at' => current_time('mysql')
494 - );
584 + 'form_fields' => $form->form_fields,
585 + 'type' => $form->type,
586 + 'has_payment' => $form->has_payment,
587 + 'conditions' => $form->conditions,
588 + 'created_by' => get_current_user_id(),
589 + 'created_at' => current_time('mysql'),
590 + 'updated_at' => current_time('mysql'),
591 + ];
495 592
496 - $newFormId = $this->model->insert($data);
593 + $newFormId = $this->model->insertGetId($data);
497 594
498 - // Ranme the form name here
595 + // Rename the form name here
499 596 wpFluent()->table('fluentform_forms')
500 597 ->where('id', $newFormId)
501 - ->update(array(
502 - 'title' => $form->title . ' (#' . $newFormId . ')'
503 - ));
598 + ->update([
599 + 'title' => $form->title . ' (#' . $newFormId . ')',
600 + ]);
504 601
505 602 $formMetas = wpFluent()->table('fluentform_form_meta')
506 603 ->where('form_id', $formId)
507 604 ->whereNot('meta_key', ['_total_views'])
@@ -506,40 +603,126 @@
506 603 ->where('form_id', $formId)
507 604 ->whereNot('meta_key', ['_total_views'])
508 605 ->get();
509 606
607 + // Required for duplicating PDF feeds
608 + $extras = [];
609 +
510 610 foreach ($formMetas as $meta) {
611 + if ('notifications' == $meta->meta_key || '_pdf_feeds' == $meta->meta_key) {
612 + $extras[$meta->meta_key][] = $meta;
613 + continue;
614 + }
615 + if ("ffc_form_settings_generated_css" == $meta->meta_key || "ffc_form_settings_meta" == $meta->meta_key) {
616 + $meta->value = str_replace('ff_conv_app_' . $formId, 'ff_conv_app_' . $newFormId, $meta->value);
617 + }
511 618 $metaData = [
512 619 'meta_key' => $meta->meta_key,
513 - 'value' => $meta->value,
514 - 'form_id' => $newFormId
620 + 'value' => $meta->value,
621 + 'form_id' => $newFormId,
515 622 ];
516 623
517 624 wpFluent()->table('fluentform_form_meta')->insert($metaData);
518 625 }
519 626
520 - do_action('flentform_form_duplicated', $newFormId);
627 + $pdfFeedMap = $this->getPdfFeedMap($extras, $newFormId);
628 + if (array_key_exists('notifications', $extras)) {
629 + $extras = $this->notificationWithPdfMap($extras, $pdfFeedMap);
630 + foreach ($extras['notifications'] as $notify) {
631 + $notifyData = [
632 + 'meta_key' => $notify->meta_key,
633 + 'value' => $notify->value,
634 + 'form_id' => $newFormId,
635 + ];
636 + wpFluent()->table('fluentform_form_meta')->insert($notifyData);
637 + }
638 + }
521 639
640 + do_action_deprecated(
641 + 'flentform_form_duplicated',
642 + [
643 + $newFormId
644 + ],
645 + FLUENTFORM_FRAMEWORK_UPGRADE,
646 + 'fluentform/form_duplicated',
647 + 'Use fluentform/form_duplicated instead of flentform_form_duplicated.'
648 + );
649 +
650 + do_action('fluentform/form_duplicated', $newFormId);
651 +
522 652 wp_send_json([
523 - 'message' => __('Form has been successfully duplicated.', 'fluentform'),
524 - 'form_id' => $newFormId,
525 - 'redirect' => admin_url('admin.php?page=fluent_forms&route=editor&form_id=' . $newFormId)
653 + 'message' => __('Form has been successfully duplicated.', 'fluentform'),
654 + 'form_id' => $newFormId,
655 + 'redirect' => admin_url('admin.php?page=fluent_forms&route=editor&form_id=' . $newFormId),
526 656 ], 200);
527 657 }
528 658
529 659 /**
530 - * Validate a form only by form title
531 - * @return void
660 + * Validate a form by form title & for duplicate name attributes
532 661 */
533 662 private function validate()
534 663 {
535 - if (!$this->request->get('title')) {
664 + $fields = $this->request->get('formFields');
665 + if ($fields) {
666 + $duplicates = Helper::getDuplicateFieldNames($fields);
667 + if ($duplicates) {
668 + $duplicateString = implode(', ', $duplicates);
669 + wp_send_json([
670 + 'title' => sprintf('Name attribute %s has duplicate value.', $duplicateString),
671 + ], 422);
672 + }
673 +
674 + $duplicateRankingFields = Helper::getRankingFieldsWithDuplicateOptionValues($fields);
675 + if ($duplicateRankingFields) {
676 + $duplicateRankingFields = implode(', ', array_unique($duplicateRankingFields));
677 + wp_send_json([
678 + 'title' => sprintf(
679 + __('Ranking field %s has duplicate option values. Please make each option value unique.', 'fluentform'),
680 + $duplicateRankingFields
681 + ),
682 + ], 422);
683 + }
684 + }
685 +
686 + if (!sanitize_text_field($this->request->get('title'))) {
536 687 wp_send_json([
537 - 'title' => 'The title field is required.'
688 + 'title' => 'The title field is required.',
538 689 ], 422);
539 690 }
540 691 }
541 692
693 + public function convertToConversational()
694 + {
695 + $formId = $this->request->get('form_id');
696 + $form = $this->fetchForm($formId);
697 +
698 + if (!$form) {
699 + wp_send_json([
700 + 'message' => __('Form Not Found! Try Again.', 'fluentform'),
701 + ], 422);
702 + }
703 +
704 + $conversationalMeta = $this->getMeta($formId, 'is_conversion_form', false);
705 +
706 + $shouldConvert = in_array($conversationalMeta, [false, 'no']);
707 +
708 + if ($shouldConvert) {
709 + $formConverted['form_fields'] = \FluentForm\App\Services\FluentConversational\Classes\Converter\Converter::convertExistingForm($form);
710 +
711 + $this->model->where('id', $formId)->update($formConverted);
712 +
713 + $conversationalMetaValue = 'yes';
714 + } else {
715 + $conversationalMetaValue = 'no';
716 + }
717 +
718 + $this->updateMeta($formId, 'is_conversion_form', $conversationalMetaValue);
719 +
720 + wp_send_json_success([
721 + 'message' => __('Form has been successfully converted.', 'fluentform'),
722 + ], 200);
723 + }
724 +
542 725 private function getAdminPermalink($route, $form)
543 726 {
544 727 $baseUrl = admin_url('admin.php?page=fluent_forms');
545 728 return $baseUrl . '&route=' . $route . '&form_id=' . $form->id;
@@ -549,28 +732,156 @@
549 732 {
550 733 $baseUrl = admin_url('admin.php?page=fluent_forms');
551 734 return $baseUrl . '&form_id=' . $form->id . '&route=settings&sub_route=form_settings#basic_settings';
552 735 }
736 +
553 737
554 - public function getAllForms()
738 + /**
739 + * Map pdf feed ID to replace with duplicated PDF feed ID when duplicating form
740 + *
741 + * @param array $extras
742 + * @param array $newFormId
743 + *
744 + * @return array
745 + */
746 + private function getPdfFeedMap($extras, $newFormId)
555 747 {
556 - $fields = $this->request->get('fields');
748 + $pdfFeedMap = [];
749 + if (array_key_exists('_pdf_feeds', $extras)) {
750 + foreach ($extras['_pdf_feeds'] as $pdf_feed) {
751 + $pdfData = [
752 + 'meta_key' => $pdf_feed->meta_key,
753 + 'value' => $pdf_feed->value,
754 + 'form_id' => $newFormId,
755 + ];
756 + $pdfFeedMap[$pdf_feed->id] = wpFluent()->table('fluentform_form_meta')->insertGetId($pdfData);
757 + }
758 + }
759 + return $pdfFeedMap;
760 + }
557 761
558 - if ($fields) {
559 - $forms = $this->model
560 - ->select($fields)
561 - ->orderBy('created_at', 'DESC')->get();
562 - } else {
563 - $forms = $this->model->orderBy('created_at', 'DESC')->get();
762 + /**
763 + * Map notification data with PDF feed map
764 + *
765 + * @param array $extras
766 + * @param array $pdfFeedMap
767 + *
768 + * @return array
769 + */
770 + private function notificationWithPdfMap($extras, $pdfFeedMap)
771 + {
772 + foreach ($extras['notifications'] as $key => $notification) {
773 + $notificationValue = json_decode($notification->value);
774 + $pdf_attachments = [];
775 + if (isset($notificationValue->pdf_attachments) && count($notificationValue->pdf_attachments)) {
776 + foreach ($notificationValue->pdf_attachments as $attachment) {
777 + $pdf_attachments[] = json_encode($pdfFeedMap[$attachment]);
778 + }
779 + }
780 + $notificationValue->pdf_attachments = $pdf_attachments;
781 + $notification->value = json_encode($notificationValue);
782 +
783 + $extras['notifications'][$key] = $notification;
564 784 }
785 + return $extras;
786 + }
787 +
788 + public function findFormLocations()
789 + {
790 + $formId = intval($this->request->get('form_id'));
791 +
792 + $excluded = ['attachment'];
793 + $post_types = get_post_types(['show_in_menu' => true], 'objects', 'or');
794 + $postTypes = [];
795 + foreach($post_types as $post_type) {
796 + $postTypeName = $post_type->name;
797 + if (in_array($postTypeName, $excluded)) {
798 + continue;
799 + }
800 + $postTypes[] = $postTypeName;
801 + }
802 +
803 + $params = array(
804 + 'post_type' => $postTypes,
805 + 'posts_per_page' => -1
806 + );
807 +
808 + $params = apply_filters_deprecated(
809 + 'fluentform_find_shortcode_params',
810 + [
811 + $params
812 + ],
813 + FLUENTFORM_FRAMEWORK_UPGRADE,
814 + 'fluentform/find_shortcode_params',
815 + 'Use fluentform/find_shortcode_params instead of fluentform_find_shortcode_params.'
816 + );
565 817
566 - wp_send_json($forms, 200);
818 + $params = apply_filters('fluentform/find_shortcode_params', $params);
819 +
820 + $formLocations = [];
821 + $posts = get_posts($params);
822 + foreach($posts as $post) {
823 +
824 + $formIds = self::getShortCodeIds($post->post_content);
825 + if(!empty($formIds) && in_array($formId,$formIds)) {
826 +
827 + $postType = get_post_type_object($post->post_type);
828 + $formLocations[] = [
829 + 'id' => $post->ID,
830 + 'name' => $postType->labels->singular_name,
831 + 'title' => (empty($post->post_title) ? $post->ID : $post->post_title),
832 + 'edit_link' => sprintf("%spost.php?post=%s&action=edit", admin_url(), $post->ID),
833 + ];
834 + }
835 + }
836 + $data = [
837 + 'locations' => $formLocations,
838 + 'status' => !empty($formLocations),
839 + ];
840 + wp_send_json($data, 200);
841 +
567 842 }
843 +
844 + public static function getShortCodeIds($content)
845 + {
846 + $ids = [];
847 + $tag = 'fluentform';
848 + $selector = 'id';
849 +
850 + if (function_exists('parse_blocks')) {
851 + $parsedBlocks = parse_blocks($content);
852 + foreach ($parsedBlocks as $block) {
853 + if (!ArrayHelper::exists($block, 'blockName') || ArrayHelper::exists($block, 'attrs.formId')) {
854 + continue;
855 + }
856 + $hasBlock = strpos($block['blockName'], 'fluentfom/guten-block') === 0;
857 + if ($hasBlock) {
858 + $ids[] = intval($block['attrs']['formId']);
859 + }
860 + }
861 + }
568 862
569 - private function getUnreadCount($formId)
570 - {
571 - return wpFluent()->table('fluentform_submissions')
572 - ->where('status', 'unread')
573 - ->where('form_id', $formId)
574 - ->count();
863 + $hasShortCode = has_shortcode($content, $tag);
864 + if(!$hasShortCode){
865 + return $ids;
866 + }
867 +
868 + preg_match_all('/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER);
869 + if (empty($matches)) {
870 + return $ids;
871 + }
872 +
873 +
874 + foreach ($matches as $shortcode) {
875 + if (count($shortcode) >= 2 && $tag === $shortcode[2]) {
876 + $parsedCode = str_replace(['[', ']', '[', ']'], '', $shortcode[0]);
877 +
878 + $result = shortcode_parse_atts($parsedCode);
879 +
880 + if (!empty($result[$selector])) {
881 + $ids[] = $result[$selector];
882 + }
883 + }
884 + }
885 + return $ids;
575 886 }
576 887 }