Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
045aa4a
Testing mode (wip, first commit)
Crabcyborg Jul 16, 2025
6f1e2e5
Add comments, use clip
Crabcyborg Jul 16, 2025
9822012
Merge branch 'master' into testing_mode
Crabcyborg Jul 25, 2025
9bae301
Set up scss for testing mode and move CSS from style tag to new scss …
Crabcyborg Jul 25, 2025
6e5abba
Move the test mode scss file, use the toggle element, use the new styles
Crabcyborg Jul 25, 2025
4feac3c
Drop weird js file
Crabcyborg Jul 25, 2025
1c41084
Disable the toggle, update the name of the dropdown option
Crabcyborg Jul 25, 2025
4dd07ba
Merge branch 'master' into testing_mode
Crabcyborg Jul 29, 2025
9ab0a0f
Add more elements to test mode container (pagination, fill form butto…
Crabcyborg Jul 29, 2025
2c23032
Some style fixes
Crabcyborg Jul 29, 2025
ad1d742
Change pagination from anchor tags to inputs
Crabcyborg Jul 29, 2025
fcbf37c
Disable test mode controls conditionally
Crabcyborg Jul 29, 2025
8290d53
Move more code out of views, remove the validation changes
Crabcyborg Jul 29, 2025
4fece62
Use helper function for options, fix wrong word used in comment
Crabcyborg Jul 29, 2025
745e74c
Match design better
Crabcyborg Jul 29, 2025
ef3f7b0
Reflect the current selected test mode role
Crabcyborg Jul 29, 2025
8c6a67f
Only check get param if enabled
Crabcyborg Jul 29, 2025
34a4b84
Add id to fill button
Crabcyborg Jul 29, 2025
3ae5a73
Add new actions for test mode, and add reset button to test mode cont…
Crabcyborg Jul 30, 2025
a02db73
Add logged out to role options
Crabcyborg Jul 30, 2025
db51478
Add the test mode container above an error message and add a hook for…
Crabcyborg Jul 30, 2025
15caaf6
Only add filter when the check passes
Crabcyborg Jul 30, 2025
fa50288
Fix scss spacing, fix phpcs issues
Crabcyborg Jul 30, 2025
4126414
Add spinner to autofill button, add AI to autofill button and add AI …
Crabcyborg Jul 31, 2025
87251e8
Add show hidden fields toggle
Crabcyborg Jul 31, 2025
70196c6
Merge branch 'master' into testing_mode
Crabcyborg Jul 31, 2025
fb70296
Use shorter fill button text
Crabcyborg Jul 31, 2025
338c6ff
Use edit forms cap
Crabcyborg Jul 31, 2025
ffe6bf5
Add enabled form actions multi-select
Crabcyborg Aug 1, 2025
d63cd61
Add ID to the dropdown options
Crabcyborg Aug 1, 2025
aa15d44
phpcs fixes
Crabcyborg Aug 1, 2025
43af616
Typo fix
Crabcyborg Aug 1, 2025
eaaef0b
Move dropdown script code
Crabcyborg Aug 1, 2025
1f4c2ab
Clean up
Crabcyborg Aug 1, 2025
23a1f04
Move style enqueue code
Crabcyborg Aug 1, 2025
1ecb188
Move script to a script file and stop using jQuery
Crabcyborg Aug 1, 2025
a69d7e6
Clean up
Crabcyborg Aug 1, 2025
c2bea3a
Clean up
Crabcyborg Aug 1, 2025
3b326e9
Disable the enabled form actions dropdown
Crabcyborg Aug 1, 2025
abb21e9
Fix a bootstrap multiselect dropdown conflict
Crabcyborg Aug 4, 2025
ff91f10
Add new pill to the preview dropdown and align it to the right
Crabcyborg Aug 4, 2025
867c75b
Add upsell
Crabcyborg Aug 4, 2025
5ef963c
Improve upsell logic
Crabcyborg Aug 4, 2025
7ffe401
Separate logic
Crabcyborg Aug 4, 2025
e96e056
Use version 3 upsell
Crabcyborg Aug 4, 2025
f7e3052
Add comments
Crabcyborg Aug 4, 2025
8312400
Add the install message
Crabcyborg Aug 4, 2025
8557f93
Add suggestion to activate the AI add-on
Crabcyborg Aug 4, 2025
b7b93b5
Make sure that the editable roles function exists
Crabcyborg Aug 5, 2025
966549a
Move more logic out of view and into smaller functions
Crabcyborg Aug 5, 2025
d8db265
Prevent showing hidden field from another page
Crabcyborg Aug 5, 2025
1822ecc
Fix issues with the multiselect dropdown when submitting to another p…
Crabcyborg Aug 5, 2025
6553800
Merge branch 'master' into testing_mode
Crabcyborg Aug 22, 2025
bd4b805
Also init multiselect on form complete
Crabcyborg Aug 22, 2025
e5ea649
Merge branch 'master' into testing_mode
Crabcyborg Aug 22, 2025
01c9b27
Show a note and leave out the test mode container when using a conver…
Crabcyborg Aug 25, 2025
32eb949
Merge branch 'master' into testing_mode
Crabcyborg Aug 25, 2025
646c9ae
Merge branch 'master' into testing_mode
Crabcyborg Aug 25, 2025
0d93af2
Merge branch 'master' into testing_mode
Crabcyborg Aug 25, 2025
7aa2b16
Try to move upgrade message logic into a new modular file
Crabcyborg Aug 25, 2025
3a76c88
Pull upgrade modal JS into new upgrade popup file
Crabcyborg Aug 25, 2025
0191fb8
Work on adding the upgrade modal to the test mode container
Crabcyborg Aug 25, 2025
cc415c4
Merge branch 'master' into testing_mode
Crabcyborg Aug 26, 2025
3809e64
Disable chunk format
Crabcyborg Aug 26, 2025
df70deb
Working on AI activation pop-up
Crabcyborg Aug 26, 2025
7e623bc
Continue working on getting an upsell pop-up into test mode
Crabcyborg Aug 26, 2025
4cfd9e9
Start pulling addon state into a new script file
Crabcyborg Aug 26, 2025
7064962
Fix some bugs
Crabcyborg Aug 26, 2025
c7e46ff
Add some comments
Crabcyborg Aug 26, 2025
2912ac3
Add todo comment
Crabcyborg Aug 26, 2025
bb0dd4f
Stop hard coding one click
Crabcyborg Aug 26, 2025
fd1264e
Align declarations
Crabcyborg Aug 26, 2025
bd2909d
Update styles, remove some alerts
Crabcyborg Aug 26, 2025
bc2d395
Add button to install Test Mode add-on
Crabcyborg Aug 27, 2025
14cb555
Tweak the spacing of the testing mode controls
Crabcyborg Aug 27, 2025
a035173
Add some responsive styling
Crabcyborg Aug 27, 2025
9fdfca9
Merge branch 'master' into testing_mode
Crabcyborg Sep 24, 2025
4ebec6f
Use ajax url global
Crabcyborg Sep 24, 2025
ede7e06
Update js
Crabcyborg Sep 24, 2025
1b28177
Change where the new pill is shown in preview dropdown
Crabcyborg Sep 24, 2025
4dc1570
Ignore testing mode compiled file
Crabcyborg Sep 24, 2025
09b608a
Use const
Crabcyborg Sep 24, 2025
0163755
Fix typo order (phpcs fixer)
Crabcyborg Sep 24, 2025
9a78053
Fix some phpcs issues
Crabcyborg Sep 24, 2025
1a293b1
Fix addonError function
Crabcyborg Sep 24, 2025
478a7f6
Add missing save and reload settings
Crabcyborg Sep 24, 2025
8e73946
Use const
Crabcyborg Sep 24, 2025
d91e6cb
Fix missing function reference
Crabcyborg Sep 24, 2025
37508f0
Tweak spacing
Crabcyborg Sep 24, 2025
4981722
Change how form key is determined
Crabcyborg Sep 24, 2025
19f052d
Add rounding to dropdowns and use a custom carat image
Crabcyborg Sep 24, 2025
a4f9536
Update dropdown font size
Crabcyborg Sep 24, 2025
8f71987
Apply more styles for the dropdown to prevent style conflicts
Crabcyborg Sep 24, 2025
41da71b
Also set font weight
Crabcyborg Sep 24, 2025
c5d4f73
Also set font weight
Crabcyborg Sep 24, 2025
045e0bc
Use cursor pointer
Crabcyborg Sep 24, 2025
bed5ef8
More tweaks to select styling
Crabcyborg Sep 24, 2025
58c0989
Add some styles to the AI button
Crabcyborg Sep 24, 2025
9d6559a
Improve how the spinner is added to the autofill button
Crabcyborg Oct 1, 2025
34e8038
Add a tooltip for enabled form actions
Crabcyborg Oct 2, 2025
60a5cae
Add new frm_additional_timestamp_text filter
Crabcyborg Oct 2, 2025
4065edf
Merge branch 'master' into testing_mode
Crabcyborg Oct 2, 2025
4a4f953
Add hover styling to test mode buttons
Crabcyborg Oct 2, 2025
eed2318
Move selected role logic out of view and into a filter so we can move…
Crabcyborg Oct 2, 2025
1f8c6fc
Fix comment syntax
Crabcyborg Oct 2, 2025
958fa71
Add some comments
Crabcyborg Oct 2, 2025
0f89530
Add some z-index rules to avoid layering issues with repeater fields
Crabcyborg Oct 2, 2025
61da2af
Tweak some test mode styles
Crabcyborg Oct 2, 2025
7cd0781
Merge branch 'master' into testing_mode
Crabcyborg Oct 6, 2025
2410d94
Merge branch 'master' into testing_mode
Crabcyborg Oct 8, 2025
5731a68
Merge branch 'master' into testing_mode
Crabcyborg Oct 8, 2025
7166d3d
Put test mode dropdown option behind new feature check
Crabcyborg Oct 9, 2025
0944011
Run eslint fix
Crabcyborg Oct 9, 2025
8696e23
Fix issue with setting fieldsUpdated when the variable does not exist…
Crabcyborg Oct 9, 2025
6a1decc
Add more comments
Crabcyborg Oct 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ js/formidable_styles.js
js/formidable_admin.js
js/bootstrap-multiselect.js
js/formidable-settings-components.js
js/frm_testing_mode.js

# Config files
*.config.js
Expand Down
6 changes: 6 additions & 0 deletions classes/controllers/FrmFormsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,12 @@ public static function preview() {
// print_emoji_styles is deprecated.
remove_action( 'wp_print_styles', 'print_emoji_styles' );

if ( FrmTestModeController::should_add_test_mode_container() ) {
do_action( 'frm_test_mode_init' );
add_action( 'wp_enqueue_scripts', 'FrmTestModeController::register_and_enqueue_required_scripts' );
add_filter( 'frm_filter_final_form', 'FrmTestModeController::maybe_add_test_mode_container', 99 );
}

$include_theme = FrmAppHelper::get_param( 'theme', '', 'get', 'absint' );
if ( $include_theme ) {
self::set_preview_query();
Expand Down
376 changes: 376 additions & 0 deletions classes/controllers/FrmTestModeController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,376 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
die( 'You are not allowed to call this page directly.' );
}

/**
* @since x.x
*/
class FrmTestModeController {

/**
* Maybe add the test mode container.
*
* @since x.x
*
* @param string $html
* @return string
*/
public static function maybe_add_test_mode_container( $html ) {
if ( '' === $html || ! self::should_add_test_mode_container() ) {
return $html;
}

/**
* @since x.x
*/
do_action( 'frm_test_mode_container' );

if ( false !== strpos( $html, '<div class="frm_form_fields' ) ) {
$html = preg_replace(
'/<div class="frm_form_fields/',
self::get_testing_mode_container() . '<div class="frm_form_fields',
$html,
1
);
} else {
// If there no form, add before an error message.
$html = '<div class="with_frm_style">' . self::get_testing_mode_container() . '</div>' . $html;
}

return $html;
}
Comment thread
Crabcyborg marked this conversation as resolved.

/**
* @since x.x
*
* @return bool
*/
public static function should_add_test_mode_container() {
if ( ! current_user_can( 'frm_edit_forms' ) ) {
return false;
}

/**
* Filter this so the add-on can enable it when applicable in other cases (like when submitting with AJAX).
*
* @since x.x
*
* @param bool $is_test_mode
*/
return (bool) apply_filters( 'frm_test_mode', (bool) FrmAppHelper::simple_get( 'testmode' ) );
}

/**
* Get the testing mode container.
*
* @since x.x
*
* @return string
*/
private static function get_testing_mode_container() {
return FrmAppHelper::clip(
function () {
self::render_testing_mode_container();
}
);
}

/**
* Render the testing mode container.
*
* @since x.x
*
* @return void
*/
private static function render_testing_mode_container() {
$form_key = self::get_form_key_from_request();
if ( ! $form_key ) {
return;
}

$form = FrmForm::getOne( $form_key );
if ( ! $form ) {
return;
}

if ( ! empty( $form->options['chat'] ) ) {
echo '<div class="frm_note_style">' . esc_html__( 'Test Mode is currently not supported for conversational forms.', 'formidable' ) . '</div>';
return;
}

$enabled = self::test_mode_addon_exists();
$ai_enabled = class_exists( 'FrmAIAppHelper' );
$roles = self::get_roles();
$selected_role = self::get_selected_role();
$pagination = apply_filters( 'frm_test_mode_pagination_buttons', false );
$disabled_required_fields_toggle_args = self::get_disabled_required_fields_toggle_args();
$show_all_hidden_fields_toggle_args = self::get_show_all_hidden_fields_toggle_args();
$form_id = is_numeric( $form_key ) ? $form_key : FrmForm::get_id_by_key( $form_key );
$should_show_upsell = self::should_show_upsell();
$should_suggest_test_mode_install = ! $enabled && ! $should_show_upsell;
$should_suggest_ai_install = $enabled && ! $ai_enabled;
$should_show_warning = $should_suggest_test_mode_install || $should_suggest_ai_install;
$form_actions = FrmFormAction::get_action_for_form( $form_id );
$enabled_form_actions = self::get_enabled_form_action_ids( $form_actions );
$test_mode_install_span_attrs = array(
'data-upgrade' => __( 'Test Mode Controls', 'formidable' ),
'data-content' => 'test-mode',
'data-medium' => 'test-mode',
'data-requires' => 'Business',
'style' => 'margin-left: auto;',
);
$ai_install_span_attrs = array(
'data-upgrade' => __( 'Autofilled forms with AI', 'formidable' ),
'data-content' => 'ai-autofill',
'data-medium' => 'test-mode',
'data-requires' => 'Business',
'style' => 'margin-left: auto;',
);

$oneclick_data = FrmAddonsController::install_link( 'ai' );
if ( isset( $oneclick_data['url'] ) ) {
$ai_install_span_attrs['data-oneclick'] = json_encode( $oneclick_data );
}

$oneclick_data = FrmAddonsController::install_link( 'test-mode' );
if ( isset( $oneclick_data['url'] ) ) {
$test_mode_install_span_attrs['data-oneclick'] = json_encode( $oneclick_data );
}

self::include_svg();

include FrmAppHelper::plugin_path() . '/classes/views/test-mode/container.php';
}

/**
* This is required for the speaker icon in the upsell to appear,
* and for the lock icon in the upgrade modals.
* It is also required for the tooltip icon used for the enabled form actions setting.
*
* @since x.x
*
* @return void
*/
private static function include_svg() {
FrmAppHelper::include_svg();
}

/**
* Check GET and POST to determine the current form key.
*
* @since x.x
*
* @return false|string
*/
private static function get_form_key_from_request() {
$form_key = FrmAppHelper::simple_get( 'form' );
if ( $form_key ) {
return $form_key;
}

$form_key = FrmAppHelper::get_post_param( 'form', '', 'sanitize_text_field' );
if ( $form_key ) {
return $form_key;
}

$form_id = FrmAppHelper::get_post_param( 'form_id', '', 'sanitize_text_field' );
if ( $form_id && is_numeric( $form_id ) ) {
return FrmForm::get_key_by_id( $form_id );
}

return false;
}

/**
* Check the request data to determine which action IDs are currently enabled.
*
* @since x.x
*
* @param array $form_actions
* @return array
*/
private static function get_enabled_form_action_ids( $form_actions ) {
$all_form_action_ids = wp_list_pluck( $form_actions, 'ID' );

/**
* Filters the list of enabled form action IDs.
* This way the add-on can modify it when required.
*
* @since x.x
*
* @param array $all_form_action_ids
*/
return apply_filters( 'frm_test_mode_enabled_form_action_ids', $all_form_action_ids );
}

/**
* Determine if the upsell should be shown.
*
* @since x.x
*
* @return bool
*/
private static function should_show_upsell() {
if ( self::test_mode_addon_exists() ) {
return false;
}

return ! in_array( FrmAddonsController::license_type(), array( 'plus', 'business', 'elite' ) );
}

/**
* Determine if the Test Mode add-on is installed and active.
*
* @since x.x
*
* @return bool
*/
private static function test_mode_addon_exists() {
if ( ! function_exists( 'load_formidable_test_mode' ) ) {
return false;
}

return FrmAppHelper::pro_is_installed();
}

/**
* Get the list of roles that can be selected in the test mode container.
*
* @since x.x
*
* @return array
*/
private static function get_roles() {
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once ABSPATH . 'wp-admin/includes/user.php';
}

$roles = get_editable_roles();
$roles['loggedout'] = array(
'name' => __( 'Logged Out', 'formidable' ),
);
return $roles;
}

/**
* Get the selected role for test mode.
*
* @since x.x
*
* @return string
*/
private static function get_selected_role() {
$selected_role = '';

/**
* Filters the selected role for test mode so the add-on can modify it when required.
*
* @since x.x
*
* @param string $selected_role
*/
return apply_filters( 'frm_test_mode_selected_role', $selected_role );
}

/**
* Get the arguments for the disabled required fields toggle.
*
* @since x.x
*
* @return array
*/
private static function get_disabled_required_fields_toggle_args() {
/**
* Filters the arguments for the disabled required fields toggle so the add-on can modify it.
*
* @since x.x
*
* @param array $args
*/
return (array) apply_filters(
'frm_test_mode_disable_required_fields_toggle_args',
array(
'echo' => true,
'off_label' => __( 'Disable Required Fields', 'formidable' ),
'show_labels' => true,
'disabled' => true,
)
);
}

/**
* Get the arguments for the show all hidden fields toggle.
*
* @since x.x
*
* @return array
*/
private static function get_show_all_hidden_fields_toggle_args() {
/**
* Filters the arguments for the show all hidden fields toggle so the add-on can modify it.
*
* @since x.x
*
* @param array $args
*/
return (array) apply_filters(
'frm_test_mode_show_all_hidden_fields_toggle_args',
array(
'echo' => true,
'off_label' => __( 'Show All Hidden Fields', 'formidable' ),
'show_labels' => true,
'disabled' => true,
)
);
}

/**
* Register and enqueue the required scripts for the test mode container Lite functionality.
*
* @since x.x
*
* @return void
*/
public static function register_and_enqueue_required_scripts() {
// These are used for the upgrade pop-up.
FrmAppController::enqueue_dialog_assets();
FrmAppController::upgrade_overlay_html();

$version = FrmAppHelper::plugin_version();

wp_enqueue_style( 'frm_testing_mode', FrmAppHelper::plugin_url() . '/css/frm_testing_mode.css', array(), $version );
Comment thread
Crabcyborg marked this conversation as resolved.
wp_enqueue_script( 'frm_testing_mode', FrmAppHelper::plugin_url() . '/js/frm_testing_mode.js', array( 'jquery', 'formidable_dom' ), $version, true );

// These are used in addon-state.js.
$admin_script_strings = array(
'active' => __( 'Active', 'formidable' ),
'installed' => __( 'Installed', 'formidable' ),
'not_installed' => __( 'Not Installed', 'formidable' ),
);
wp_localize_script( 'frm_testing_mode', 'frm_admin_js', $admin_script_strings );

self::register_and_enqueue_multiselect_dropdown_requirements();
}
Comment thread
Crabcyborg marked this conversation as resolved.

/**
* Register and enqueue the required scripts for the multiselect dropdown.
*
* @since x.x
*
* @return void
*/
private static function register_and_enqueue_multiselect_dropdown_requirements() {
// Enqueue multiselect dropdown requirements.
$plugin_url = FrmAppHelper::plugin_url();
$version = FrmAppHelper::plugin_version();

wp_register_script( 'popper', FrmAppHelper::plugin_url() . '/js/popper.min.js', array( 'jquery' ), '1.16.0', true );
wp_register_script( 'bootstrap_tooltip', $plugin_url . '/js/bootstrap.min.js', array( 'jquery', 'popper' ), '4.6.1', true );
wp_register_script( 'bootstrap-multiselect', $plugin_url . '/js/bootstrap-multiselect.js', array( 'jquery', 'bootstrap_tooltip', 'popper' ), '1.1.1', true );
wp_register_script( 'formidable_dom', $plugin_url . '/js/admin/dom.js', array( 'jquery', 'jquery-ui-dialog', 'wp-i18n' ), $version, true );

wp_enqueue_script( 'bootstrap-multiselect' );
wp_enqueue_script( 'formidable_dom' );
}
}
Comment thread
Crabcyborg marked this conversation as resolved.
Loading